
; ******** Source: basic_glcd.asm
     1                          ; Troy's HBC-56 - BASIC (For Graphics LCD screen)
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          

; ******** Source: basic_hbc56_core.asm
     1                          ; Troy's HBC-56 - BASIC
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          

; ******** Source: ../kernel\hbc56kernel.inc
     1                          ; 6502 - HBC-56 Kernel Include file for user code
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          ;
    10                          
    11                          !cpu w65c02
    12                          !initmem $FF
    13                          cputype = $65c02
    14                          

; ******** Source: ../kernel\kernel.o.lmap
     1                          	HBC56_RST_VECTOR	= $fcb1	; ?
     2                          	AY_ENV_SHAPE_SAW1	= $8	; unused
     3                          	tmsConsoleBackspace	= $e9e3	; ?
     4                          	NES_RAM_SIZE	= $1
     5                          	UART_ZP_START	= $2a
     6                          	TMS_LT_RED	= $9	; unused
     7                          	UART_STATUS_RCVR_OVERRUN	= $20	; unused
     8                          	HBC56_TMP	= $7ccc
     9                          	lcdDisplayOff	= $ed9b	; ?
    10                          	TILEMAP_SIZE	= $1
    11                          	KB_SCANCODE_ESC	= $76	; unused
    12                          	AY_ENV_SHAPE_SAW2	= $c	; unused
    13                          	TILEMAP_TMP_OUTPUT_ROW	= $7a83
    14                          	TMS_GFX_TILE_WIDTH	= $8
    15                          	lcdCurrentLine	= $eecf	; ?
    16                          	LCD_RAM_END	= $7b82
    17                          	LCD_ZP_SIZE	= $2
    18                          	TMS_SPRITE_SIZE	= $8
    19                          	LCD_EXTENDED	= $3c	; ?
    20                          	KB_SCANCODE_ARROW_RIGHT	= $f4	; unused
    21                          	LCD_CMD_SHIFT_DISPLAY	= $8	; unused
    22                          	KB_CAPS_LOCK	= $8
    23                          	KB_EXT_KEY	= $e0
    24                          	VIA_RAM_SIZE	= $1
    25                          	HBC56_VSYNC_CALLBACK	= $7ce3
    26                          	isLower	= $e000
    27                          	TMS_R1_SPRITE_MAG2	= $1	; unused
    28                          	bitmapLineH	= $ea86
    29                          	KB_BUFFER_MASK	= $f
    30                          	KB_SCANCODE_SLASH_FORWARD	= $4a	; unused
    31                          	AY_PORTB	= $f	; unused
    32                          	TMS_R1_RAM_16K	= $80
    33                          	lcdLineFour	= $ef94	; ?
    34                          	lcdConsolePrint	= $f051	; unused
    35                          	AY_PORTA	= $e	; unused
    36                          	TMS_R1_SPRITE_MAG1	= $0	; unused
    37                          	TMS_FPS	= $3c
    38                          	lcdLineThreeEnd	= $ef25	; ?
    39                          	kbInit	= $f267
    40                          	VIA_TMP	= $7c82	; unused
    41                          	tmsSetAddressNextRow	= $e586	; unused
    42                          	START_BYTE	= $7b1f
    43                          	UART_IRQ_BIT	= $4
    44                          	tmsModeText	= $e644	; unused
    45                          	VIA_REG_IFR	= $d
    46                          	bitmapLineV	= $eb17
    47                          	_bitmapLineWide	= $eba7	; ?
    48                          	lcdCharScroll	= $edfd
    49                          	LCD_CMD_SET_CGRAM_ADDR	= $40	; unused
    50                          	_tmsSendKb	= $e6a7	; unused
    51                          	UART_STATUS_RX_REG_FULL	= $1
    52                          	tmsReg1SetFields	= $e5e5
    53                          	BITMAP_ZP_START	= $1e
    54                          	BITMAP_LINE_STYLE_ODD	= $7b1e
    55                          	END_BYTE	= $7b20
    56                          	JMP_OPCODE	= $4c
    57                          	hbc56IntHandler	= $fc2a
    58                          	TILEMAP_RAM_START	= $7a00
    59                          	KB_SCANCODE_SCROLL_LOCK	= $7e	; unused
    60                          	KB_RAM_END	= $7cc6
    61                          	AY_ENV_SHAPE_HOLD	= $1
    62                          	TMS_R0_MODE_GRAPHICS_II	= $2
    63                          	TILEMAP_ADDR	= $18
    64                          	KB_SHIFT_LEFT_MAP_BYTE	= $2
    65                          	VIA_IO_ADDR_IFR	= $7ffd	; unused
    66                          	TILEMAP_SIZE_Y_8	= $0
    67                          	VIA_IO_ADDR_T1C_H	= $7ff5	; unused
    68                          	MEMORY_ZP_END	= $34
    69                          	TMS_R1_SPRITE_8	= $0	; unused
    70                          	VIA_REG_T1L_H	= $7
    71                          	BITMAP_X	= $7b17
    72                          	BITMAP_Y	= $7b18
    73                          	KB_SCANCODE_PRTSCR	= $92	; unused
    74                          	LCD_BASIC	= $38	; ?	; unused
    75                          	KB_SCANCODE_SLASH_BACK	= $5d	; unused
    76                          	VIA_IO_ADDR_T1C_L	= $7ff4	; unused
    77                          	TILEMAP_SIZE_X_64	= $2
    78                          	AY_WRITE	= $1
    79                          	UART_STATUS_CARRIER_DETECT	= $4	; unused
    80                          	VIA_REG_T1L_L	= $6
    81                          	KB_PRESSED_MAP	= $7ca0
    82                          	TMS9918_ZP_START	= $24
    83                          	tmsDecPosConsole	= $e8c4
    84                          	UART_CTL_WORD_8BIT_1SB	= $14	; unused
    85                          	HBC56_CONSOLE_FLAG_LCD	= $20	; unused
    86                          	TMS_CYAN	= $7
    87                          	ASCII_NEWLINE	= $a
    88                          	HBC56_TITLE	= $f53c
    89                          	memcpyMultiPage	= $e0bf	; unused
    90                          	LCD_ROWS	= $4
    91                          	KB_SCANCODE_NUM_LOCK	= $77	; unused
    92                          	TILEMAP_RAM_END	= $7b16
    93                          	lcdGraphicsMode	= $ecaa
    94                          	VIA_DIR_OUTPUT	= $ff	; unused
    95                          	TILEMAP_ZP_SIZE	= $6
    96                          	lcdPrint	= $edda
    97                          	KB_BUFFER_TAIL	= $7c8f
    98                          	tmsSetRegister	= $e5bc
    99                          	hbc56Tms9918Int	= $fc5b	; ?
   100                          	lcdGotoLineEnd	= $eed2	; ?
   101                          	KB_SCANCODE_NUMPAD_ENTER	= $da	; unused
   102                          	TILEMAP_FIXED_ADDRESS	= $7b00
   103                          	UART_STATUS_TX_REG_EMPTY	= $2
   104                          	UART_RX_BUFFER_XOFF_SIZE	= $c0
   105                          	KB_FLAGS	= $7c86
   106                          	lcdGotoLine	= $ef69	; ?
   107                          	HBC56_NMI_VECTOR	= $7e04
   108                          	KB_SCANCODE_SQUARE_LEFT	= $54	; unused
   109                          	LCD_CMD_SHIFT_CURSOR	= $0	; unused
   110                          	lcdRead	= $edd3
   111                          	BITMAP_ZP_END	= $24
   112                          	lcdLineOne	= $ef7c	; ?
   113                          	UART_CTL_CLOCK_DIV_64	= $2
   114                          	toUpper	= $e06b	; unused
   115                          	VIA_IO_ADDR	= $7ff0
   116                          	tableBitsFromLeft	= $e150	; unused
   117                          	LCD_CMD_ENTRY_MODE	= $4	; unused
   118                          	NES_TMP	= $7cc6	; unused
   119                          	HBC56_META_TITLE_END	= $7ce1
   120                          	uartFlowCtrlXoff	= $f1f0	; ?
   121                          	SFXMAN_RAM_START	= $7c83
   122                          	uartInWait	= $f1f9
   123                          	uartOutString	= $f23d	; unused
   124                          	RTI_OPCODE	= $40
   125                          	KB_SCANCODE_PAGE_UP	= $fd	; unused
   126                          	AY_ENV_SHAPE_FADE_OUT	= $9	; unused
   127                          	LINE_WIDTH	= $7b1f
   128                          	lcdReadLine	= $efbb
   129                          	TMS_VRAM_SPRITE_ATTR_ADDRESS	= $3b00
   130                          	LCD_CMD_SET_DRAM_ADDR	= $80
   131                          	NOTE_FREQ_AS8	= 7458.619999999999890860635787248611	; unused
   132                          	HBC56_TMP_Y	= $7ccf
   133                          	KB_SCANCODE_TILDE	= $e	; unused
   134                          	HBC56_TITLE_LEN	= $1a
   135                          	UART_IO_PORT	= $20
   136                          	TMS9918_RAM_END	= $7b58
   137                          	AY_S0_ADDR	= $7f40	; unused
   138                          	TMS9918_ZP_SIZE	= $2
   139                          	HBC56_TMP_X	= $7cce
   140                          	NOTE_FREQ_AS5	= 932.330000000000040927261579781771	; unused
   141                          	TMS_MED_GREEN	= $2	; unused
   142                          	TMS_WHITE	= $f
   143                          	LCD_CMD_DISPLAY_CURSOR_BLINK	= $1
   144                          	LCD_ADDR_LINE2	= $10
   145                          	KB_SCANCODE_WINDOWS_RIGHT	= $a7	; unused
   146                          	HBC56_KERNEL_ZP_END	= $38
   147                          	AY_S1_WRITE	= $7f45	; unused
   148                          	NOTE_FREQ_AS4	= 466.160000000000025011104298755527	; unused
   149                          	LCD_CMD_SHIFT	= $10
   150                          	VIA_REG_DDR_B	= $2
   151                          	LCD_ADDR_LINE3	= $8
   152                          	NOTE_FREQ_AS7	= 3729.309999999999945430317893624306	; unused
   153                          	TMS_TMP_ADDRESS	= $24
   154                          	KB_SCANCODE_PERIOD	= $49	; unused
   155                          	VIA_REG_DDR_A	= $3
   156                          	tableBitFromLeft	= $e130
   157                          	NOTE_FREQ_AS6	= 1864.660000000000081854523159563541	; unused
   158                          	LCD_ADDR_LINE1	= $0
   159                          	AY_NOISE_GEN	= $6	; unused
   160                          	NOTE_FREQ_AS1	= 58.270000000000003126388037344441	; unused
   161                          	BITMAP_X2	= $7b19
   162                          	AY_S0_WRITE	= $7f41	; unused
   163                          	NOTE_FREQ_AS0	= 29.140000000000000568434188608080	; unused
   164                          	tmsSetAddressRead	= $e5a8
   165                          	VIA_RAM_START	= $7c82
   166                          	LCD_CMD_CLEAR	= $1
   167                          	NOTE_FREQ_AS3	= 233.080000000000012505552149377763	; unused
   168                          	UART_RX_BUFFER_TAIL	= $2b
   169                          	tmsSetPatternRead	= $e95c	; unused
   170                          	LCD_ADDR_LINE4	= $18
   171                          	AY_S1_ADDR	= $7f44	; unused
   172                          	NOTE_FREQ_AS2	= 116.540000000000006252776074688882	; unused
   173                          	BITMAP_X1	= $7b17
   174                          	UART_RX_BUFFER	= $7b82
   175                          	TMS_R1_SPRITE_16	= $2	; unused
   176                          	TMS_GFX_PIXELS_Y	= $c0	; unused
   177                          	TMS_GFX_PIXELS_X	= $100	; unused
   178                          	KB_SCANCODE_NUMPAD_MULTIPLY	= $7c	; unused
   179                          	HBC56_DISABLE_SFXMAN	= $1
   180                          	tmsSetAddressWrite	= $e592
   181                          	D	= $7b24
   182                          	TMS_MAGENTA	= $d	; unused
   183                          	LCD_GRAPHICS	= $1
   184                          	LCD_IO_PORT	= $2
   185                          	tmsConsoleScrollLine	= $e82f
   186                          	KB_SCANCODE_CTRL_RIGHT	= $94	; unused
   187                          	_tmsSendEmptyPage	= $e6e6
   188                          	HAVE_GRAPHICS_LCD	= $1
   189                          	KB_BUFFER_SIZE	= $10
   190                          	KB_SCANCODE_COMMA	= $41	; unused
   191                          	HBC56_TITLE_TEXT	= $f53c
   192                          	AY_R10	= $a
   193                          	BITMAP_TMP1	= $7b1f
   194                          	LCD_CMD_12864B_EXTENDED	= $4
   195                          	AY_IO_PORT	= $40
   196                          	AY_R11	= $b
   197                          	NES_LEFT	= $2	; unused
   198                          	AY_R12	= $c
   199                          	TMS_R1_DISP_BLANK	= $0	; unused
   200                          	LCD_RAM_SIZE	= $2a
   201                          	KB_NUM_LOCK	= $10	; unused
   202                          	BITMAP_TMP3	= $7b21
   203                          	hbc56LogoPatt	= $f942
   204                          	kernelMain	= $fcb1	; ?
   205                          	AY_R13	= $d
   206                          	hbc56LogoPattEnd	= $faba	; unused
   207                          	BITMAP_TMP2	= $7b20
   208                          	tilemapSetActive	= $f0d6	; ?
   209                          	ASCII_CR	= $d
   210                          	AY_R14	= $e
   211                          	KB_SCANCODE_PAGE_DOWN	= $fa	; unused
   212                          	BITMAP_TMP5	= $7b23
   213                          	kbIntHandler	= $f2a2
   214                          	IO_PORT_BASE_ADDRESS	= $7f00
   215                          	AY_R15	= $f
   216                          	BITMAP_TMP4	= $7b22
   217                          	isDigit	= $e01e
   218                          	AY_R16	= $10	; unused
   219                          	HAVE_TMS9918	= $1
   220                          	UART_CTL_MASTER_RESET	= $3
   221                          	AY_R17	= $11	; unused
   222                          	BITMAP_TMP6	= $7b24
   223                          	KB_SCANCODE_TAB	= $d	; unused
   224                          	HBC56_KERNEL_ZP_START	= $18
   225                          	TMS9918_IRQ_BIT	= $1
   226                          	HBC56_BORDER	= $4
   227                          	TMS_R1_MODE_MULTICOLOR	= $8
   228                          	lcdTextMode	= $ecbb
   229                          	TMS_R0_MODE_MULTICOLOR	= $0
   230                          	lcdNextLine2	= $efae	; unused
   231                          	TMS_DK_BLUE	= $4
   232                          	LCD_CMD_DISPLAY_CURSOR	= $2
   233                          	lcdClear	= $ed80	; ?
   234                          	TMS_VRAM_SPRITE_PATT_ADDRESS	= $1800
   235                          	lcdNextLine4	= $ef9c
   236                          	HBC56_CONSOLE_FLAG_NOWAIT	= $10
   237                          	lcdGraphicsSetRow	= $eccc
   238                          	KB_SCANCODE_ENTER	= $5a	; unused
   239                          	KB_IO_PORT	= $80
   240                          	AY_ENV_SHAPE_ATTACK	= $4
   241                          	UART_STATUS_IRQ	= $80	; unused
   242                          	X	= $7b21
   243                          	TILEMAP_INVERT_ADDR	= $3
   244                          	NES_DOWN	= $4	; unused
   245                          	tmsReg1ClearFields	= $e5ef
   246                          	Y	= $7b21
   247                          	NES_SELECT	= $20	; unused
   248                          	LCD_CMD_ENTRY_MODE_SHIFT	= $1	; unused
   249                          	TILEMAP_RAM_SIZE	= $107
   250                          	hbc56Stop	= $fe67
   251                          	lcdChar	= $edf6
   252                          	lcdInt8	= $ee4e	; unused
   253                          	UART_RX_BUFFER_SIZE	= $100
   254                          	KB_BUFFER	= $7c90
   255                          	DEFAULT_HBC56_NMI_VECTOR	= $ffe0	; unused
   256                          	COL_BYTE	= $7b1f
   257                          	HAVE_TILEMAP	= $1	; unused
   258                          	TILEMAP_HEIGHT_TILES	= $6
   259                          	NES1_IO_ADDR	= $7f82
   260                          	lcdDetect	= $edbf
   261                          	UART_CTL_WORD_7BIT_OPB_1SB	= $c	; unused
   262                          	KB_SCANCODE_NUMPAD_PLUS	= $79	; unused
   263                          	NES2_IO_ADDR	= $7f83
   264                          	BITMAP_RAM_END	= $7b26
   265                          	BITMAP_ZP_SIZE	= $4
   266                          	KB_SCANCODE_F2	= $6	; unused
   267                          	lcdCursorBlinkOn	= $edb6
   268                          	HBC56_TITLE_TEXT_LEN	= $1a
   269                          	lcdConsoleOut	= $f02b
   270                          	NES_UP	= $8	; unused
   271                          	KB_SCANCODE_F3	= $4	; unused
   272                          	VIA_DIR_INPUT	= $0	; unused
   273                          	DELAY_L	= $36
   274                          	TMS_TXT_TILES_X	= $28
   275                          	ASCII_BACKSPACE	= $8
   276                          	TMS_TXT_TILES_Y	= $18
   277                          	KB_SCANCODE_F1	= $5	; unused
   278                          	KB_SCANCODE_SEMICOLON	= $4c	; unused
   279                          	c	= $20
   280                          	KB_SCANCODE_F6	= $b	; unused
   281                          	TMS_R1_DISP_ACTIVE	= $40
   282                          	tmsInitColorTable	= $e756
   283                          	KB_SCANCODE_F7	= $83	; unused
   284                          	KB_SCANCODE_HOME	= $ec	; unused
   285                          	DELAY_H	= $37
   286                          	KB_SCANCODE_F4	= $c	; unused
   287                          	tmsSetPosTmpAddress	= $e7ed
   288                          	uartInNoWait	= $f203	; unused
   289                          	hbc56Reset	= $fe64	; unused
   290                          	KB_SCANCODE_F5	= $3	; unused
   291                          	hbc56CustomDelayMs	= $fe6b	; unused
   292                          	lcdLineThree	= $ef8c	; ?
   293                          	_tmsWaitReg	= $e582
   294                          	uartOut	= $f226	; ?
   295                          	KB_TMP_X	= $7c87
   296                          	KB_SCANCODE_F8	= $a	; unused
   297                          	hbc56LogoLcd	= $f800
   298                          	HBC56_KERNEL_RAM_START	= $7a00
   299                          	KB_TMP_Y	= $7c88	; unused
   300                          	KB_SCANCODE_F9	= $1	; unused
   301                          	tmsConsolePrint	= $e9ac	; unused
   302                          	lcdLineTwo	= $ef84	; ?
   303                          	TILEMAP_BUFFER_ADDR	= $0
   304                          	uartIrq	= $f1c1
   305                          	TMS_BLACK	= $1
   306                          	TILEMAP_WIDTH_TILES	= $5
   307                          	HAVE_LCD	= $1
   308                          	HBC56_META_TITLE	= $7cd0
   309                          	KB_SCANCODE_SQUARE_RIGHT	= $5b	; unused
   310                          	tmsConsoleNewline	= $e9bc	; ?
   311                          	LCD_CMD_8BITMODE	= $10
   312                          	AY_S1	= $7f44
   313                          	NOTE_FREQ_C8	= 4186.010000000000218278728425502777	; unused
   314                          	KB_IRQ_BIT	= $2
   315                          	tmsModeGraphicsII	= $e623	; unused
   316                          	AY_S0	= $7f40
   317                          	NOTE_FREQ_A8	= $1b80	; unused
   318                          	HBC56_TICKS	= $7cc9
   319                          	HBC56_SECONDS_H	= $7ccb
   320                          	memcpySinglePage	= $e0a3	; unused
   321                          	tmsModeGraphicsI	= $e610
   322                          	NOTE_FREQ_G8	= 6271.930000000000291038304567337036	; unused
   323                          	AY_ADDR	= $0
   324                          	NOTE_FREQ_E8	= 5274.039999999999963620211929082870	; unused
   325                          	TMS_R1_RAM_4K	= $0	; unused
   326                          	AY_ENV_SHAPE_ALTERNATE	= $2
   327                          	NOTE_FREQ_DS8	= 4978.029999999999745341483503580093	; unused
   328                          	tmsInitEntireColorTable	= $e754	; ?
   329                          	TILEMAP_TMP_BUFFER_ADDR	= $1a
   330                          	TMS_GREY	= $e
   331                          	NES_B	= $40	; unused
   332                          	HBC56_SECONDS_L	= $7cca
   333                          	AY_PSG1	= $4
   334                          	UART_CTL_WORD_7BIT_EPB_1SB	= $8	; unused
   335                          	NES_A	= $80	; unused
   336                          	LCD_COLUMNS	= $10
   337                          	TMS9918_IO_PORT	= $10
   338                          	UART_RAM_END	= $7c82
   339                          	AY_PSG0	= $0
   340                          	UART_FLOWCTRL_XON	= $11
   341                          	LCD_CMD_FUNCTIONSET	= $20
   342                          	DEFAULT_HBC56_RST_VECTOR	= $8000
   343                          	NOTE_FREQ_C0	= 16.350000000000001421085471520200	; unused
   344                          	NOTE_FREQ_A1	= $37	; unused
   345                          	NOTE_FREQ_G2	= $62	; unused
   346                          	NOTE_FREQ_E3	= 164.810000000000002273736754432321
   347                          	NOTE_FREQ_DS4	= 311.129999999999995452526491135359	; unused
   348                          	KB_SCANCODE_CTRL_LEFT	= $14	; unused
   349                          	lcdImageVflip	= $ed27	; unused
   350                          	TILE_SIZE	= $8	; unused
   351                          	NOTE_FREQ_A0	= 27.500000000000000000000000000000	; unused
   352                          	NOTE_FREQ_E2	= 82.409999999999996589394868351519	; unused
   353                          	NOTE_FREQ_DS5	= 622.250000000000000000000000000000	; unused
   354                          	tmsReg0ClearFields	= $e5dd
   355                          	LCD_CMD_HOME	= $2
   356                          	UART_STATUS_CLEAR_TO_SEND	= $8	; unused
   357                          	NOTE_FREQ_G3	= $c4	; unused
   358                          	NOTE_FREQ_C1	= 32.700000000000002842170943040401	; unused
   359                          	NOTE_FREQ_G0	= 24.500000000000000000000000000000	; unused
   360                          	NOTE_FREQ_E1	= 41.200000000000002842170943040401	; unused
   361                          	NOTE_FREQ_DS6	= 1244.509999999999990905052982270718	; unused
   362                          	UART_DATA	= $7f21
   363                          	VIA_IO_ADDR_T2C_H	= $7ff9	; unused
   364                          	NOTE_FREQ_C2	= 65.409999999999996589394868351519	; unused
   365                          	NOTE_FREQ_A3	= $dc	; unused
   366                          	NOTE_FREQ_E0	= 20.600000000000001421085471520200	; unused
   367                          	NOTE_FREQ_DS7	= 2489.019999999999981810105964541435	; unused
   368                          	TMS9918_TMP_BUFFER	= $7b30
   369                          	NOTE_FREQ_G1	= $31	; unused
   370                          	NOTE_FREQ_A2	= $6e	; unused
   371                          	NOTE_FREQ_C3	= 130.810000000000002273736754432321	; unused
   372                          	UART_ZP_END	= $2e
   373                          	NOTE_FREQ_DS0	= 19.449999999999999289457264239900	; unused
   374                          	NOTE_FREQ_C4	= 261.629999999999995452526491135359	; unused
   375                          	NOTE_FREQ_A5	= $370	; unused
   376                          	NOTE_FREQ_G6	= 1567.980000000000018189894035458565	; unused
   377                          	NOTE_FREQ_E7	= 2637.019999999999981810105964541435	; unused
   378                          	NOTE_FREQ_DS1	= 38.890000000000000568434188608080	; unused
   379                          	HAVE_KEYBOARD	= $1
   380                          	NOTE_FREQ_A4	= $1b8	; unused
   381                          	NOTE_FREQ_E6	= 1318.509999999999990905052982270718	; unused
   382                          	_bitmapLineTall	= $ebf8	; ?
   383                          	hbc56HighBell	= $fde5	; ?
   384                          	NOTE_FREQ_G7	= 3135.960000000000036379788070917130	; unused
   385                          	NOTE_FREQ_C5	= 523.250000000000000000000000000000	; unused
   386                          	tmsConsoleHome	= $e8e1	; unused
   387                          	_bitmapOffset	= $ea38
   388                          	NOTE_FREQ_DS2	= 77.780000000000001136868377216160	; unused
   389                          	NOTE_FREQ_G4	= $188	; unused
   390                          	NOTE_FREQ_E5	= 659.250000000000000000000000000000	; unused
   391                          	VIA_IO_ADDR_T2C_L	= $7ff8	; unused
   392                          	NOTE_FREQ_C6	= 1046.500000000000000000000000000000	; unused
   393                          	NOTE_FREQ_A7	= $dc0	; unused
   394                          	BCD_RAM_START	= $7c83
   395                          	HBC56_META_TITLE_MAX_LEN	= $10
   396                          	isDigitX	= $e030	; unused
   397                          	NOTE_FREQ_DS3	= 155.560000000000002273736754432321	; unused
   398                          	NOTE_FREQ_E4	= 329.629999999999995452526491135359	; unused
   399                          	NOTE_FREQ_G5	= 783.990000000000009094947017729282	; unused
   400                          	NOTE_FREQ_A6	= $6e0	; unused
   401                          	NOTE_FREQ_C7	= $82d	; unused
   402                          	VIA_RAM_END	= $7c83
   403                          	AY_INACTIVE	= $3	; unused
   404                          	TMS_SPRITE_SIZE2X	= $10	; unused
   405                          	tmsSetPosWriteText	= $e8fa	; ?
   406                          	KB_SCANCODE_F11	= $78	; unused
   407                          	AY_S0_READ	= $7f42	; unused
   408                          	tmsInitTextTable	= $e739	; ?
   409                          	LCD_TMP2	= $29
   410                          	lcdCursorOn	= $eda4	; unused
   411                          	KB_SCANCODE_F10	= $9	; unused
   412                          	VIA_REG_PORT_A	= $1
   413                          	LCD_TMP1	= $28
   414                          	KB_SCANCODE_NUMPAD_PERIOD	= $71	; unused
   415                          	VIA_REG_PORT_B	= $0
   416                          	KB_SCANCODE_F12	= $7	; unused
   417                          	kbNextScancode	= $f3c0
   418                          	lcdBackspace	= $ee1a
   419                          	KB_SCANCODE_WINDOWS_LEFT	= $9f	; unused
   420                          	BCD_RAM_END	= $7c86
   421                          	ASCII_RETURN	= $a
   422                          	lcdWaitPreserve	= $edcd
   423                          	TILEMAP_TILES_ADDR	= $2
   424                          	tilemapRenderToLcd	= $f113	; unused
   425                          	LCD_CMD_DISPLAY	= $8
   426                          	TILEMAP_TMP_TILE_SIZE	= $7a88
   427                          	TMS_R1_INT_ENABLE	= $20
   428                          	lcdLineOneEnd	= $eee1	; ?
   429                          	bitmapLine	= $eb60	; unused
   430                          	UART_CTL_WORD_8BIT_OPAR_1SB	= $1c	; unused
   431                          	isSpace	= $e049	; unused
   432                          	hbc56BootScreen	= $faba
   433                          	AY_S1_READ	= $7f46	; unused
   434                          	KB_SCANCODE_END	= $e9	; unused
   435                          	TMS_GFX_TILE_HEIGHT	= $8
   436                          	KB_SCANCODE_SHIFT_RIGHT	= $59
   437                          	TMS_LT_BLUE	= $5	; unused
   438                          	TMS_R0_EXT_VDP_ENABLE	= $1	; unused
   439                          	TILEMAP_STRUCTURE_SIZE	= $7
   440                          	uartOutNoBsCheck	= $f22c	; ?
   441                          	KB_SCANCODE_ALT_LEFT	= $11	; unused
   442                          	lcdLineTwoEnd	= $ef03	; ?
   443                          	HBC56_INT_VECTOR	= $7e00
   444                          	LINE_HEIGHT	= $7b20
   445                          	VIA_REG_IER	= $e
   446                          	tmsIncPosConsole	= $e8a3
   447                          	INT_IO_PORT	= $df
   448                          	KB_PRESSED_MAP_BYTES	= $20
   449                          	VIA_REG_ACR	= $b
   450                          	STR_ADDR_H	= $35
   451                          	NES_RAM_END	= $7cc9
   452                          	memsetSinglePage	= $e101
   453                          	TMS_FONT_DATA	= $e271
   454                          	tmsSetPatternTmpAddressII	= $e90a	; unused
   455                          	kbWaitForScancode	= $f3ab
   456                          	LCD_CMD_SHIFT_LEFT	= $0
   457                          	tmsReg0SetFields	= $e5d3
   458                          	tmsPrint	= $e962
   459                          	KB_SCANCODE_APOS	= $52	; unused
   460                          	STR_ADDR_L	= $34
   461                          	tmsSetPosConsole	= $e8e7
   462                          	KB_SHIFT_RIGHT_MAP_BYTE	= $b
   463                          	AY_CLOCK_FREQ	= $1e8480
   464                          	tmsSetBackground	= $e5cf
   465                          	BITMAP_ADDR_H	= $20
   466                          	TMS_R1_MODE_GRAPHICS_II	= $0
   467                          	UART_RX_BUFFER_XON_SIZE	= $4
   468                          	VIA_IO_ADDR_ACR	= $7ffb	; unused
   469                          	uartFlowCtrlXon	= $f1e5	; ?
   470                          	TILEMAP_SIZE_X_32	= $1
   471                          	VIA_IO_ADDR_IER	= $7ffe	; unused
   472                          	ASCII_BELL	= $7	; unused
   473                          	BCD_TMP3	= $7c85
   474                          	TMS_MED_RED	= $8	; unused
   475                          	DISPLAY_MODE	= $c
   476                          	UART_CTL_WORD_8BIT_EPAR_1SB	= $18	; unused
   477                          	BCD_TMP2	= $7c84
   478                          	LCD_ZP_END	= $2a
   479                          	toLower	= $e073	; unused
   480                          	BCD_TMP1	= $7c83
   481                          	MEM_SRC	= $30
   482                          	AY_ENABLES	= $7
   483                          	lcdWait	= $edc7	; ?
   484                          	UART_CTL_WORD_7BIT_OPB_2SB	= $4	; unused
   485                          	lcdInit	= $ed6e
   486                          	LCD_RAM_START	= $7b58
   487                          	TMS_LT_GREEN	= $3	; unused
   488                          	_tmsWaitData	= $e579
   489                          	tmsSetColorTmpAddressII	= $e906	; unused
   490                          	TILEMAP_SIZE_X_16	= $0
   491                          	HAVE_MATH_INC	= $1
   492                          	TILEMAP_TMP_TILES_W	= $7a86
   493                          	KB_SCANCODE_B	= $32	; unused
   494                          	hbc56Bell	= $fe17	; unused
   495                          	KB_SCANCODE_C	= $21	; unused
   496                          	TMS_TXT_PIXELS_X	= $f0	; unused
   497                          	lcdCursorOff	= $edad
   498                          	HBC56_KERNEL_RAM_SIZE	= $2e7	; unused
   499                          	TMS_TXT_PIXELS_Y	= $c0	; unused
   500                          	lcdLineFourEnd	= $ef47	; ?
   501                          	KB_SCANCODE_A	= $1c	; unused
   502                          	TMS_GFX_TILES_Y	= $18
   503                          	KB_PRESSED_MAP_SIZE	= $fe	; unused
   504                          	KB_SCANCODE_F	= $2b	; unused
   505                          	kbIsPressed	= $f38e	; unused
   506                          	TMS_R0_MODE_TEXT	= $0
   507                          	TMS_GFX_TILES_X	= $20
   508                          	TILEMAP_DIRTY_ADDR	= $4
   509                          	KB_SCANCODE_G	= $34	; unused
   510                          	TMS_R0_MODE_GRAPHICS_I	= $0
   511                          	tmsSetSpriteTmpAddress	= $e7e4	; unused
   512                          	bitmapClear	= $e9f9	; unused
   513                          	KB_CB_RELEASED	= $7c8b
   514                          	KB_SCANCODE_D	= $23	; unused
   515                          	TMS_R1_MODE_GRAPHICS_I	= $0
   516                          	KB_SCANCODE_E	= $24	; unused
   517                          	TILEMAP_ZP_START	= $18
   518                          	KB_SHIFT_DOWN	= $1	; unused
   519                          	KB_SCANCODE_J	= $3b	; unused
   520                          	KB_CB_PRESSED	= $7c89
   521                          	KB_SCANCODE_K	= $42	; unused
   522                          	KB_SHIFT_RIGHT_MAP_BIT	= $40
   523                          	HBC56_CONSOLE_FLAGS	= $7ccd
   524                          	AY_ENV_SHAPE	= $d
   525                          	LCD_CMD_ENTRY_MODE_DECREMENT	= $0	; unused
   526                          	KB_SCANCODE_H	= $33	; unused
   527                          	kbReadAscii	= $f428	; unused
   528                          	KB_BUFFER_HEAD	= $7c8e
   529                          	KB_SCANCODE_I	= $43	; unused
   530                          	viaIntHandler	= $f539
   531                          	KB_SCANCODE_N	= $31	; unused
   532                          	tmsTileXyAtPixelXy	= $e7aa	; unused
   533                          	UART_CTL_CLOCK_DIV_16	= $1	; unused
   534                          	nesWaitForPress	= $f24a
   535                          	hbc56LogoInd	= $f900
   536                          	KB_SCANCODE_O	= $44	; unused
   537                          	memcpyMultiPagePort	= $e0e1	; unused
   538                          	KB_SCANCODE_L	= $4b	; unused
   539                          	bin2bcd8	= $e07b	; unused
   540                          	KB_SCANCODE_M	= $3a	; unused
   541                          	KB_SCANCODE_ARROW_UP	= $f5	; unused
   542                          	lcdCurrentLine2	= $eec2	; unused
   543                          	UART_RX_BUFFER_HEAD	= $2a
   544                          	KB_SCANCODE_R	= $2d	; unused
   545                          	_tmsSendPage	= $e6b0	; ?
   546                          	LCD_CMD_ENTRY_MODE_INCREMENT	= $2	; unused
   547                          	tmsSetPosWrite	= $e8ed	; unused
   548                          	KB_SCANCODE_S	= $1b	; unused
   549                          	hbc56FontLcd	= $f600
   550                          	tilemapRenderRowToLcd	= $f0ec
   551                          	KB_SCANCODE_P	= $4d	; unused
   552                          	TMS_DK_RED	= $6	; unused
   553                          	LCD_CMD_SHIFT_RIGHT	= $4	; unused
   554                          	TILEMAP_TMP_BUF_ROW	= $7a80
   555                          	KB_SCANCODE_Q	= $15	; unused
   556                          	NOTE_FREQ_GS8	= 6644.880000000000109139364212751389	; unused
   557                          	BITMAP_LINE_STYLE	= $7b1d
   558                          	KB_CURRENT_STATE	= $7c8d
   559                          	KB_SCANCODE_V	= $2a	; unused
   560                          	NOTE_FREQ_CS8	= 4434.920000000000072759576141834259	; unused
   561                          	KB_SCANCODE_W	= $1d	; unused
   562                          	HBC56_CONSOLE_FLAG_NES	= $40
   563                          	lcdCurrentLine4	= $eead
   564                          	UART_CTL_WORD_7BIT_EPB_2SB	= $0	; unused
   565                          	kbScancodeToAscii	= $f3d5
   566                          	LCD_CMD	= $7f02
   567                          	KB_SCANCODE_T	= $2c	; unused
   568                          	KB_SHIFT_LEFT_MAP_BIT	= $20
   569                          	TMS_TRANSPARENT	= $0	; unused
   570                          	TILEMAP_TMP_TILES_ADDR	= $1c
   571                          	KB_SCANCODE_U	= $3c	; unused
   572                          	SFXMAN_RAM_END	= $7c83
   573                          	NOTE_FREQ_GS4	= 415.300000000000011368683772161603	; unused
   574                          	tmsSendBytes	= $e6ea
   575                          	NOTE_FREQ_CS5	= 554.370000000000004547473508864641	; unused
   576                          	VIA_REG_T2C_H	= $9
   577                          	lcdHex8	= $ee84	; unused
   578                          	KB_SCANCODE_Z	= $1a	; unused
   579                          	LCD_ZP_START	= $28
   580                          	NOTE_FREQ_CS4	= 277.180000000000006821210263296962	; unused
   581                          	NOTE_FREQ_GS5	= 830.610000000000013642420526593924	; unused
   582                          	KB_SCANCODE_MINUS	= $4e	; unused
   583                          	isUpper	= $e00c
   584                          	TMS_VRAM_NAME_ADDRESS	= $3800
   585                          	UART_IRQ	= $3
   586                          	NES_RAM_START	= $7cc6
   587                          	LCD_CMD_2LINE	= $8
   588                          	NOTE_FREQ_GS6	= 1661.220000000000027284841053187847	; unused
   589                          	NOTE_FREQ_CS7	= 2217.460000000000036379788070917130	; unused
   590                          	KB_SCANCODE_X	= $22	; unused
   591                          	KB_SCANCODE_PAUSE	= $e1
   592                          	KB_IO_ADDR	= $7f80
   593                          	TILEMAP_SIZE_Y_32	= $8
   594                          	memcpySinglePagePort	= $e0b1	; unused
   595                          	NOTE_FREQ_CS6	= 1108.730000000000018189894035458565	; unused
   596                          	NOTE_FREQ_GS7	= 3322.440000000000054569682106375694	; unused
   597                          	TMS_REGISTER_DATA	= $e571
   598                          	TMS_MODEL	= $26be
   599                          	KB_SCANCODE_Y	= $35	; unused
   600                          	NOTE_FREQ_GS0	= 25.960000000000000852651282912120	; unused
   601                          	NOTE_FREQ_CS1	= 34.649999999999998578914528479800	; unused
   602                          	HAVE_BITMAP	= $1	; unused
   603                          	BITMAP_Y2	= $7b1a
   604                          	bitmapFilledRect	= $ec72	; unused
   605                          	VIA_REG_T2C_L	= $8
   606                          	ROM_BANK_REG	= $8	; unused
   607                          	HBC56_USER_ZP_START	= $38	; unused
   608                          	NOTE_FREQ_CS0	= 17.320000000000000284217094304040	; unused
   609                          	NOTE_FREQ_GS1	= 51.909999999999996589394868351519	; unused
   610                          	LCD_CMD_EXT_GRAPHICS_ENABLE	= $2
   611                          	UART_CTL_RX_INT_ENABLE	= $80
   612                          	KB_SCANCODE_CAPS_LOCK	= $58
   613                          	tableInvBitFromRight	= $e148	; unused
   614                          	tmsInitPattTable	= $e6f9	; ?
   615                          	TMS9918_IRQ	= $1
   616                          	HBC56_CONSOLE_FLAG_CURSOR	= $80	; unused
   617                          	NOTE_FREQ_GS2	= 103.829999999999998294697434175760	; unused
   618                          	NOTE_FREQ_CS3	= 138.590000000000003410605131648481	; unused
   619                          	tmsModeMulticolor	= $e657	; unused
   620                          	NOTE_FREQ_CS2	= 69.299999999999997157829056959599	; unused
   621                          	NOTE_FREQ_GS3	= 207.650000000000005684341886080801	; unused
   622                          	BITMAP_Y1	= $7b18
   623                          	TILEMAP_TMP_TILES_H	= $7a87
   624                          	TILEMAP_SIZE_Y_16	= $4
   625                          	KB_IRQ	= $2
   626                          	VIA_IO_PORT	= $f0
   627                          	HBC56_VIA_CALLBACK	= $7ce5
   628                          	_tmsSendX8	= $e6b2
   629                          	KB_SCANCODE_NUMPAD_5	= $73	; unused
   630                          	AY_CHA	= $0
   631                          	lcdImage	= $ece7
   632                          	KB_SCANCODE_ALT_RIGHT_	= $91	; unused
   633                          	bitmapFill	= $ea00	; unused
   634                          	bitmapXor	= $ea1d	; unused
   635                          	KB_SCANCODE_NUMPAD_4	= $6b	; unused
   636                          	AY_CHB	= $1
   637                          	lcdNextLine	= $efb8	; ?
   638                          	KB_RAM_SIZE	= $3a
   639                          	tmsSetPatternWrite	= $e956	; unused
   640                          	lcdDisplayOn	= $ed92
   641                          	KB_SCANCODE_NUMPAD_7	= $6c	; unused
   642                          	UART_RAM_START	= $7b82
   643                          	AY_CHC	= $2
   644                          	KB_SCANCODE_NUMPAD_6	= $74	; unused
   645                          	MEMORY_ZP_SIZE	= $6
   646                          	tilemapInit	= $f05e
   647                          	KB_SCANCODE_NUMPAD_1	= $69	; unused
   648                          	KEY_MAP_SHIFTED	= $f4b9	; ?
   649                          	AY_READ	= $2
   650                          	KB_SCANCODE_NUMPAD_0	= $70	; unused
   651                          	KB_SCANCODE_NUMPAD_3	= $7a	; unused
   652                          	HBC56_LOGO	= $4
   653                          	VIA_IRQ	= $5
   654                          	tableBitFromRight	= $e140	; unused
   655                          	KB_SCANCODE_NUMPAD_2	= $72	; unused
   656                          	TMS9918_CONSOLE_LINE_LEN	= $7b2b
   657                          	KB_SCANCODE_NUMPAD_MINUS	= $7b	; unused
   658                          	BITMAP_RAM_START	= $7b16
   659                          	TILEMAP_TMP_TILE_ROW	= $7a82
   660                          	uartInit	= $f1a5	; unused
   661                          	hbc56CustomDelay	= $ffe3
   662                          	UART_STATUS_FRAMING_ERROR	= $10	; unused
   663                          	HBC56_BACKGROUND	= $f
   664                          	AY_ENV_SHAPE_FADE_IN_STOP	= $4	; unused
   665                          	HAVE_UART	= $1
   666                          	MEM_DST	= $2e
   667                          	TMS_DK_YELLOW	= $a	; unused
   668                          	TILEMAP_TMP_2	= $7a85
   669                          	UART_STATUS_PARITY_ERROR	= $40	; unused
   670                          	lcdScrollUp	= $efcc	; ?
   671                          	KB_SCANCODE_NUMPAD_9	= $7d	; unused
   672                          	LCD_INITIALIZE	= $38	; ?
   673                          	KB_SCANCODE_NUMPAD_8	= $75	; unused
   674                          	AY_CHN	= $3	; unused
   675                          	AY_ENV_SHAPE_TRIANGLE	= $e	; unused
   676                          	hbc56Delay	= $ffe1
   677                          	tableInvBitFromLeft	= $e138
   678                          	TILEMAP_TMP_1	= $7a84
   679                          	STYLE_BYTE	= $7b20
   680                          	KB_SCANCODE_2	= $1e	; unused
   681                          	AY_CHB_TONE_H	= $3	; unused
   682                          	KB_SCANCODE_3	= $26	; unused
   683                          	kbResetCallbacks	= $f291	; unused
   684                          	NES_IO_PORT	= $82
   685                          	TMS9918_RAM_SIZE	= $32
   686                          	KB_SCANCODE_0	= $45	; unused
   687                          	TMS9918_RAM_START	= $7b26
   688                          	AY_CHA_TONE_L	= $0
   689                          	AY_CHC_TONE_H	= $5	; unused
   690                          	AY_ENV_SHAPE_CONTINUE	= $8
   691                          	KB_SCANCODE_1	= $16	; unused
   692                          	HBC56_TEXT	= $4
   693                          	HBC56_META_VECTOR	= $dffc
   694                          	cputype	= $65c02	; unused
   695                          	KB_SCANCODE_6	= $36	; unused
   696                          	HBC56_KERNEL_RAM_END	= $7ce7
   697                          	AY_CHB_TONE_L	= $2	; unused
   698                          	KB_SCANCODE_7	= $3d	; unused
   699                          	AY_ENV_SHAPE_FADE_IN	= $d	; unused
   700                          	tmsModeReset	= $e5f7
   701                          	KB_SCANCODE_DELETE	= $f1	; unused
   702                          	KB_SCANCODE_4	= $25	; unused
   703                          	KB_SCANCODE_MENU	= $af	; unused
   704                          	KB_SCANCODE_SPACEBAR	= $29	; unused
   705                          	AY_CHA_TONE_H	= $1
   706                          	AY_CHC_TONE_L	= $4	; unused
   707                          	KB_SCANCODE_5	= $2e	; unused
   708                          	MEMORY_ZP_START	= $2e
   709                          	tmsSetPosRead	= $e900	; unused
   710                          	nes1Pressed	= $f257	; unused
   711                          	VIA_REG_T1C_H	= $5
   712                          	INT_CTRL_ADDRESS	= $7fdf
   713                          	STR_ADDR	= $34
   714                          	AY_ENV_PERIOD_H	= $c
   715                          	tmsHex8	= $e7b7	; unused
   716                          	VIA_IO_ADDR_T1L_H	= $7ff7	; unused
   717                          	TILEMAP_ZP_END	= $1e
   718                          	KEY_MAP	= $f439	; ?
   719                          	KB_SCANCODE_8	= $3e	; unused
   720                          	KB_RAM_START	= $7c86
   721                          	KB_SCANCODE_9	= $46	; unused
   722                          	TILEMAP_DEFAULT_BUFFER_ADDRESS	= $7a00
   723                          	VIA_REG_T1C_L	= $4
   724                          	AY_ENV_PERIOD_L	= $b
   725                          	bitmapClearPixel	= $ea70	; unused
   726                          	KB_PAUSE_KEY	= $e1
   727                          	VIA_IO_ADDR_T1L_L	= $7ff6	; unused
   728                          	KB_CTRL_DOWN	= $2	; unused
   729                          	NES_RIGHT	= $1	; unused
   730                          	nes2Pressed	= $f25f	; unused
   731                          	MEM_LEN	= $32
   732                          	bitmapRect	= $ec49	; unused
   733                          	VIA_IO_ADDR_PORT_A	= $7ff1	; unused
   734                          	UART_CTL_WORD_8BIT_2SB	= $10
   735                          	NES_START	= $10	; unused
   736                          	HBC56_META_TITLE_LEN	= $7ce2
   737                          	memsetMultiPage	= $e10d
   738                          	UART_REG	= $7f20
   739                          	LCD_MODEL	= $3240
   740                          	KB_SCANCODE_SHIFT_LEFT	= $12
   741                          	VIA_IO_ADDR_PORT_B	= $7ff0	; unused
   742                          	isAlNum	= $e02a	; unused
   743                          	AY_CHA_AMPL	= $8
   744                          	LAST_MODULE_RAM_END	= $7cc9
   745                          	TMS_R1_MODE_TEXT	= $10
   746                          	tmsConsoleOut	= $e975
   747                          	TMS9918_REG	= $7f11
   748                          	BITMAP_RAM_SIZE	= $10
   749                          	bitmapXorPixel	= $ea7b	; unused
   750                          	KB_SCANCODE_NUMPAD_DIVIDE	= $ca	; unused
   751                          	DEFAULT_HBC56_INT_VECTOR	= $ffe0
   752                          	VIA_IRQ_BIT	= $10
   753                          	TMS_VRAM_PATT_ADDRESS	= $2000
   754                          	bitmapSetPixel	= $ea65
   755                          	KB_SCANCODE_EQUAL	= $55	; unused
   756                          	KB_RELEASE	= $f0
   757                          	tmsInitSpriteTable	= $e775	; ?
   758                          	KB_SCANCODE_ARROW_DOWN	= $f2	; unused
   759                          	LCD_CMD_EXT_GRAPHICS_ADDR	= $80
   760                          	TILEMAP_TMP_BUF_COL	= $7a81
   761                          	END_OFFSET	= $7b21
   762                          	UART_RX_BUFFER_BYTES	= $2c
   763                          	lcdHome	= $ed89	; ?
   764                          	isAlpha	= $e018
   765                          	ayInit	= $e158
   766                          	TMS9918_RAM	= $7f10
   767                          	LCD_CMD_DISPLAY_ON	= $4
   768                          	UART_RX_FLAGS	= $2d
   769                          	AY_R1	= $1
   770                          	NOTE_FREQ_B8	= 7902.130000000000109139364212751389	; unused
   771                          	LCD_DATA	= $7f03
   772                          	KB_STATUS_ADDR	= $7f81
   773                          	AY_R0	= $0
   774                          	AY_R3	= $3
   775                          	NOTE_FREQ_F8	= 5587.649999999999636202119290828705	; unused
   776                          	AY_R2	= $2
   777                          	NOTE_FREQ_D8	= 4698.630000000000109139364212751389	; unused
   778                          	TMS_DK_GREEN	= $c	; unused
   779                          	AY_R5	= $5
   780                          	AY_CHC_AMPL	= $a	; unused
   781                          	NOTE_FREQ_FS8	= 5919.909999999999854480847716331482	; unused
   782                          	AY_R4	= $4
   783                          	AY_R7	= $7
   784                          	KB_ALT_DOWN	= $4	; unused
   785                          	AY_R6	= $6
   786                          	TMS_TXT_TILE_HEIGHT	= $8
   787                          	AY_R9	= $9
   788                          	NOTE_FREQ_B0	= 30.870000000000000994759830064140	; unused
   789                          	NOTE_FREQ_F2	= 87.310000000000002273736754432321	; unused
   790                          	NOTE_FREQ_D3	= 146.830000000000012505552149377763	; unused
   791                          	NOTE_FREQ_FS4	= 369.990000000000009094947017729282	; unused
   792                          	TMS_VRAM_COLOR_ADDRESS+2	= $0
   793                          	tmsSetPatternTmpAddressBank1	= $e940	; unused
   794                          	VIA_IO_ADDR_DDR_A	= $7ff3	; unused
   795                          	AY_R8	= $8
   796                          	NOTE_FREQ_B1	= 61.740000000000001989519660128281	; unused
   797                          	NOTE_FREQ_D2	= 73.420000000000001705302565824240	; unused
   798                          	NOTE_FREQ_FS5	= 739.990000000000009094947017729282	; unused
   799                          	UART_FLOWCTRL_XOFF	= $13
   800                          	TMS_R0_EXT_VDP_DISABLE	= $0
   801                          	tmsSetPatternTmpAddressBank0	= $e923	; unused
   802                          	NOTE_FREQ_F3	= 174.610000000000013642420526593924	; unused
   803                          	NOTE_FREQ_F0	= 21.829999999999998294697434175760	; unused
   804                          	NOTE_FREQ_D1	= 36.710000000000000852651282912120	; unused
   805                          	NOTE_FREQ_FS6	= 1479.980000000000018189894035458565	; unused
   806                          	TMS9918_CONSOLE_Y	= $7b29
   807                          	TMS_LT_YELLOW	= $b	; unused
   808                          	KB_SCANCODE_ARROW_LEFT	= $eb	; unused
   809                          	NOTE_FREQ_B2	= 123.469999999999998863131622783840	; unused
   810                          	NOTE_FREQ_D0	= 18.350000000000001421085471520200	; unused
   811                          	NOTE_FREQ_FS7	= 2959.960000000000036379788070917130	; unused
   812                          	TMS9918_CONSOLE_X	= $7b28
   813                          	PIX_ADDR	= $1e
   814                          	tmsSetPatternTmpAddressBank2	= $e94b	; unused
   815                          	VIA_IO_ADDR_DDR_B	= $7ff2	; unused
   816                          	NOTE_FREQ_F1	= 43.649999999999998578914528479800	; unused
   817                          	NOTE_FREQ_B3	= 246.939999999999997726263245567679	; unused
   818                          	TILEMAP_TILE_SIZE_PX	= $7
   819                          	HBC56_KERNEL_START	= $e000
   820                          	TMS9918_ZP_END	= $28
   821                          	HAVE_AY3891X	= $1
   822                          	NOTE_FREQ_FS0	= 23.120000000000000994759830064140	; unused
   823                          	TMS_R1_INT_DISABLE	= $0	; unused
   824                          	AY_CHB_AMPL	= $9	; unused
   825                          	NOTE_FREQ_B4	= 493.879999999999995452526491135359	; unused
   826                          	NOTE_FREQ_F6	= 1396.910000000000081854523159563541	; unused
   827                          	NOTE_FREQ_D7	= 2349.320000000000163709046319127083	; unused
   828                          	NOTE_FREQ_FS1	= 46.250000000000000000000000000000	; unused
   829                          	NOTE_FREQ_B5	= 987.769999999999981810105964541435	; unused
   830                          	NOTE_FREQ_D6	= 1174.660000000000081854523159563541	; unused
   831                          	TMS_TXT_TILE_WIDTH	= $6
   832                          	tmsSetPosTmpAddressText	= $e80a
   833                          	tmsSetPatternTmpAddress	= $e923
   834                          	NOTE_FREQ_F7	= 2793.829999999999927240423858165741	; unused
   835                          	NOTE_FREQ_FS2	= 92.500000000000000000000000000000	; unused
   836                          	NOTE_FREQ_F4	= 349.230000000000018189894035458565	; unused
   837                          	NOTE_FREQ_D5	= 587.330000000000040927261579781771	; unused
   838                          	LOGO_BUFFER	= $3000
   839                          	NOTE_FREQ_B6	= 1975.529999999999972715158946812153	; unused
   840                          	TMS9918_CONSOLE_SIZE_X	= $7b2a
   841                          	KB_SCANCODE_BACKSPACE	= $66	; unused
   842                          	NOTE_FREQ_FS3	= $b9	; unused
   843                          	NOTE_FREQ_D4	= 293.660000000000025011104298755527	; unused
   844                          	tmsInit	= $e665
   845                          	TMP_STYLE	= $7b23
   846                          	NOTE_FREQ_F5	= 698.460000000000036379788070917130
   847                          	NOTE_FREQ_B7	= 3951.070000000000163709046319127083	; unused
   848                          	KB_SCANCODE_INSERT	= $f0	; unused

; ******** Source: ../kernel\hbc56kernel.inc
    15                          
    16                          

; ******** Source: ../lib\ut\math.inc
     1                          ; 6502
     2                          ;
     3                          ; Math macros
     4                          ;
     5                          ; Copyright (c) 2020 Troy Schrapel
     6                          ;
     7                          ; This code is licensed under the MIT license
     8                          ;
     9                          ; https://github.com/visrealm/hbc-56
    10                          ;
    11                          ;
    12                          
    13                          HAVE_MATH_INC = 1
    14                          
    15                          !macro lsr2 {
    16                                  lsr
    17                                  lsr
    18                          }
    19                          
    20                          !macro lsr3 {
    21                                  +lsr2
    22                                  lsr
    23                          }
    24                          
    25                          !macro lsr4 {
    26                                  +lsr3
    27                                  lsr
    28                          }
    29                          
    30                          !macro lsr5 {
    31                                  +lsr4
    32                                  lsr
    33                          }
    34                          
    35                          !macro lsr6 {
    36                                  +lsr5
    37                                  lsr
    38                          }
    39                          
    40                          !macro lsr7 {
    41                                  +lsr6
    42                                  lsr
    43                          }
    44                          
    45                          !macro div2   { lsr }
    46                          !macro div4   { +lsr2 }
    47                          !macro div8   { +lsr3 }
    48                          !macro div16  { +lsr4 }
    49                          !macro div32  { +lsr5 }
    50                          !macro div64  { +lsr6 }
    51                          !macro div128 { +lsr7 }
    52                          
    53                          !macro asl2 {
    54                                  asl
    55                                  asl
    56                          }
    57                          
    58                          !macro asl3 {
    59                                  +asl2
    60                                  asl
    61                          }
    62                          
    63                          !macro asl4 {
    64                                  +asl3
    65                                  asl
    66                          }
    67                          
    68                          !macro asl5 {
    69                                  +asl4
    70                                  asl
    71                          }
    72                          
    73                          !macro asl6 {
    74                                  +asl5
    75                                  asl
    76                          }
    77                          
    78                          !macro asl7 {
    79                                  +asl6
    80                                  asl
    81                          }
    82                          
    83                          !macro mul2   { asl }
    84                          !macro mul4   { +asl2 }
    85                          !macro mul8   { +asl3 }
    86                          !macro mul16  { +asl4 }
    87                          !macro mul32  { +asl5 }
    88                          !macro mul64  { +asl6 }
    89                          !macro mul128 { +asl7 }
    90                          
    91                          
    92                          
    93                          ; -----------------------------------------------------------------------------
    94                          ; +dec16: decement a 16-bit value
    95                          ; -----------------------------------------------------------------------------
    96                          ; Inputs:
    97                          ;  addr: address containing LSB of value to decrement
    98                          ; -----------------------------------------------------------------------------
    99                          !macro dec16 .addr {
   100                            lda .addr
   101                            bne +
   102                            dec .addr + 1
   103                          +
   104                            dec .addr
   105                          }
   106                          
   107                          ; -----------------------------------------------------------------------------
   108                          ; +inc16: increment a 16-bit value
   109                          ; -----------------------------------------------------------------------------
   110                          ; Inputs:
   111                          ;  addr: address containing LSB of value to increment
   112                          ; -----------------------------------------------------------------------------
   113                          !macro inc16 .addr {
   114                            inc .addr
   115                            bne +
   116                            inc .addr + 1
   117                          +
   118                          }
   119                          
   120                          ; -----------------------------------------------------------------------------
   121                          ; +cmp16: compare two 16-bit values in memory
   122                          ; -----------------------------------------------------------------------------
   123                          ; Inputs:
   124                          ;  left:  address containing LSB of left value to comapre
   125                          ;  right: address containing LSB of right value to comapre
   126                          ; Outputs:
   127                          ;  C set if right < left
   128                          ;  Z set if right == left
   129                          ; -----------------------------------------------------------------------------
   130                          !macro cmp16 .left, .right {
   131                            lda .left + 1
   132                            cmp .right + 1
   133                          	bne +
   134                          	lda .left
   135                          	cmp .right
   136                          +
   137                          }
   138                          
   139                          ; -----------------------------------------------------------------------------
   140                          ; +cmp16: compare two 16-bit values in memory
   141                          ; -----------------------------------------------------------------------------
   142                          ; Inputs:
   143                          ;  value: immediate value to compare
   144                          ;  x:     msb
   145                          ;  a:     lsb
   146                          ; -----------------------------------------------------------------------------
   147                          !macro cmp16xa .value {
   148                            cpx #>.value
   149                          	bne .doneCmpXa
   150                          	cmp #<.value
   151                          .doneCmpXa
   152                          }
   153                          
   154                          ; -----------------------------------------------------------------------------
   155                          ; +sub16: subtract 16 bit numbers
   156                          ; -----------------------------------------------------------------------------
   157                          ; Inputs:
   158                          ;  left:  address containing LSB of left value
   159                          ;  right: address containing LSB of right value
   160                          ; Outputs:
   161                          ;  res:   address containing LSB of result
   162                          ; -----------------------------------------------------------------------------
   163                          !macro sub16 .left, .right, .res {
   164                            sec
   165                            lda .left
   166                            sbc .right
   167                            sta .res
   168                            lda .left + 1
   169                            sbc .right + 1
   170                            sta .res + 1
   171                          }
   172                          
   173                          ; -----------------------------------------------------------------------------
   174                          ; +sub16: subtract 16 bit numbers - result in ax registers
   175                          ; -----------------------------------------------------------------------------
   176                          ; Inputs:
   177                          ;  left:  address containing LSB of left value
   178                          ;  right: address containing LSB of right value
   179                          ; Outputs:
   180                          ;  a:     result msb
   181                          ;  x:     result lsb
   182                          ; -----------------------------------------------------------------------------
   183                          !macro sub16 .left, .right {
   184                            sec
   185                            lda .left
   186                            sbc .right
   187                            tax
   188                            lda .left + 1
   189                            sbc .right + 1
   190                          }
   191                          
   192                          
   193                          ; -----------------------------------------------------------------------------
   194                          ; +add16: add 16 bit numbers - result in ax registers
   195                          ; -----------------------------------------------------------------------------
   196                          ; Inputs:
   197                          ;  left:  address containing LSB of left value
   198                          ;  right: address containing LSB of right value
   199                          ; Outputs:
   200                          ;  a:     result msb
   201                          ;  x:     result lsb
   202                          ; -----------------------------------------------------------------------------
   203                          !macro add16 .left, .right {
   204                            clc
   205                            lda .left
   206                            adc .right
   207                            tax
   208                            lda .left + 1
   209                            adc .right + 1
   210                          }
   211                          
   212                          
   213                          ; -----------------------------------------------------------------------------
   214                          ; +add16Imm: add 16 bit numbers - result stored to res
   215                          ; -----------------------------------------------------------------------------
   216                          ; Inputs:
   217                          ;  left:  address containing LSB of left value
   218                          ;  imm:   immediate value to add
   219                          ; Outputs:
   220                          ;  res: address to store result
   221                          ; -----------------------------------------------------------------------------
   222                          !macro add16Imm .left, .imm, .res {
   223                            clc
   224                            lda .left
   225                            adc #<.imm
   226                            sta .res
   227                            lda .left + 1
   228                            adc #>.imm
   229                            sta .res + 1
   230                          }
   231                          
   232                          
   233                          ; -----------------------------------------------------------------------------
   234                          ; +subImm8From16: subtract an 8 bit number from a 16 bit number
   235                          ; -----------------------------------------------------------------------------
   236                          ; Inputs:
   237                          ;  left:  address containing LSB of left value
   238                          ;  right: immediate 8-bit value
   239                          ; Outputs:
   240                          ;  res:   address containing LSB of result
   241                          ; -----------------------------------------------------------------------------
   242                          !macro subImm8From16 .left, .right, .res {
   243                            sec
   244                            lda .left
   245                            sbc #.right
   246                            sta .res
   247                            lda .left + 1
   248                            sbc #0
   249                            sta .res + 1
   250                          }
   251                          
   252                          ; -----------------------------------------------------------------------------
   253                          ; +incBcd: increment a BCD byte (inc instruction doesn't work in bcd mode)
   254                          ; -----------------------------------------------------------------------------
   255                          ; Inputs:
   256                          ;  addr:  address containing BCD value
   257                          ; -----------------------------------------------------------------------------
   258                          !macro incBcd .addr {
   259                            lda .addr
   260                            sed
   261                            clc
   262                            adc #1
   263                            cld
   264                            sta .addr
   265                          }
   266                          
   267                          ; -----------------------------------------------------------------------------
   268                          ; +decBcd: decrement a BCD byte (inc instruction doesn't work in bcd mode)
   269                          ; -----------------------------------------------------------------------------
   270                          ; Inputs:
   271                          ;  addr:  address containing BCD value
   272                          ; -----------------------------------------------------------------------------
   273                          !macro decBcd .addr {
   274                            lda .addr
   275                            sed
   276                            sec
   277                            sbc #1
   278                            cld
   279                            sta .addr

; ******** Source: ../kernel\hbc56kernel.inc
    17                          

; ******** Source: ../lib\ut\memory.inc
     1                          ; 6502
     2                          ;
     3                          ; Memory subroutines and macros
     4                          ;
     5                          ; Copyright (c) 2020 Troy Schrapel
     6                          ;
     7                          ; This code is licensed under the MIT license
     8                          ;
     9                          ; https://github.com/visrealm/hbc-56
    10                          ;
    11                          ;
    12                          
    13                          ; -----------------------------------------------------------------------------
    14                          ; store16: Write a 16-bit immediate value to memory
    15                          ; -----------------------------------------------------------------------------
    16                          ; Inputs:
    17                          ;	.dst: destination address
    18                          ;	.val16: 16-bit value
    19                          ; -----------------------------------------------------------------------------
    20                          !macro store16 .dst, .val16 {
    21                                  lda #<.val16
    22                                  sta .addr
    23                                  lda #>.val16
    24                                  sta .addr + 1
    25                          }
    26                          
    27                          ; -----------------------------------------------------------------------------
    28                          ; memcpy: Copy a fixed number of bytes from .src to dest
    29                          ; -----------------------------------------------------------------------------
    30                          ; Inputs:
    31                          ;	.src: source address
    32                          ;	.dst: destination address
    33                          ;	.cnt: number of bytes
    34                          ; -----------------------------------------------------------------------------
    35                          !macro memcpy .dst, .src, .cnt {
    36                          !if .cnt <= 0 {
    37                          	!error "memcpy: invalid count: ", .cnt
    38                          } else if .cnt <= 8 {
    39                          	!for i, 0, .cnt - 1 {
    40                          		lda .src + i
    41                          		sta .dst + i
    42                          	}
    43                          } else { !if .cnt <= 256 {
    44                          	ldx #0
    45                          -
    46                          	lda .src, x
    47                          	sta .dst, x
    48                          	inx
    49                          	cpx #(.cnt & $ff)	
    50                          	bne -
    51                          } else {
    52                          	lda #<.src
    53                          	sta MEM_SRC
    54                          	lda #>.src
    55                          	sta MEM_SRC + 1
    56                          
    57                          	lda #<.dst
    58                          	sta MEM_DST
    59                          	lda #>.dst
    60                          	sta MEM_DST + 1
    61                          
    62                          
    63                          		lda #<.cnt
    64                          		sta MEM_LEN
    65                          		lda #>.cnt
    66                          		sta MEM_LEN + 1
    67                          		jsr memcpyMultiPage
    68                          	}
    69                          }
    70                          }
    71                          
    72                          !macro setMemCpySrc .src {
    73                          	lda #<.src
    74                          	sta MEM_SRC
    75                          	lda #>.src
    76                          	sta MEM_SRC + 1
    77                          }
    78                          
    79                          !macro setMemCpyDst .dst {
    80                          	lda #<.dst
    81                          	sta MEM_DST
    82                          	lda #>.dst
    83                          	sta MEM_DST + 1
    84                          }
    85                          
    86                          !macro setMemCpySrcInd .srcRef {
    87                          	lda .srcRef
    88                          	sta MEM_SRC
    89                          	lda .srcRef + 1
    90                          	sta MEM_SRC + 1
    91                          }
    92                          
    93                          !macro setMemCpyDstInd .dstRef {
    94                          	lda .dstRef
    95                          	sta MEM_DST
    96                          	lda .dstRef + 1
    97                          	sta MEM_DST + 1
    98                          }
    99                          
   100                          !macro memcpySinglePage .bytes {
   101                          
   102                          	!if .bytes <= 0 {
   103                          		!error "memcpySinglePage: invalid count: ", .bytes
   104                          	}	
   105                          
   106                          	ldy #.bytes
   107                          	jsr memcpySinglePage
   108                          }
   109                          
   110                          
   111                          ; -----------------------------------------------------------------------------
   112                          ; memcpyPort: Copy a fixed number of bytes from .src ram to dest port
   113                          ; -----------------------------------------------------------------------------
   114                          ; Inputs:
   115                          ;	.src: source address
   116                          ;	.dst: destination address
   117                          ;	.cnt: number of bytes
   118                          ; -----------------------------------------------------------------------------
   119                          !macro memcpyPort .dst, .src, .cnt {
   120                          	!if .cnt <= 0 {
   121                          		!error "memcpyPort: invalid count: ", .cnt
   122                          	}
   123                          	
   124                          	lda #<.src
   125                          	sta MEM_SRC
   126                          	lda #>.src
   127                          	sta MEM_SRC + 1
   128                          
   129                          	lda #<.dst
   130                          	sta MEM_DST
   131                          	lda #>.dst
   132                          	sta MEM_DST + 1
   133                          
   134                          	!if .cnt <= 256 {
   135                          		ldy #<.cnt					
   136                          		jsr memcpySinglePagePort
   137                          	} else {
   138                          		lda #<.cnt
   139                          		sta MEM_LEN
   140                          		lda #>.cnt
   141                          		sta MEM_LEN + 1
   142                          		jsr memcpyMultiPagePort
   143                          	}
   144                          }
   145                          
   146                          !zone {
   147                          
   148                          ; -----------------------------------------------------------------------------
   149                          ; memset: Set a fixed number of bytes to a single value
   150                          ; -----------------------------------------------------------------------------
   151                          ; Inputs:
   152                          ;	.dst: destination address
   153                          ;	val: the byte value
   154                          ;	.cnt: number of bytes
   155                          ; -----------------------------------------------------------------------------
   156                          !macro memset .dst, .val, .cnt {
   157                          !if .cnt <= 0 {
   158                          	!error "memset: invalid count: ", .cnt
   159                          } else if .cnt <= 8 {
   160                          	lda #.val
   161                          	!for i, 0, .cnt - 1 {
   162                          	sta .dst + i
   163                          	}
   164                          } else if .cnt <= 256 {
   165                          	ldx #<.cnt
   166                          	lda #.val
   167                          -
   168                          	dex
   169                          	sta .dst, x
   170                          	cpx #0
   171                          	bne -
   172                          } else {
   173                          	lda #<.dst
   174                          	sta MEM_DST
   175                          	lda #>.dst
   176                          	sta MEM_DST + 1
   177                          	lda #<.cnt
   178                          	sta MEM_LEN
   179                          	lda #>.cnt
   180                          	sta MEM_LEN + 1
   181                          	lda #.val
   182                          	jsr memsetMultiPage
   183                          }
   184                          }
   185                          
   186                          

; ******** Source: ../kernel\hbc56kernel.inc
    18                          

; ******** Source: ../lib\gfx\tms9918.inc
     1                          ; 6502 - TMS9918 VDP Macros
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          
    10                          
    11                          
    12                          
    13                          ; -----------------------------------------------------------------------------
    14                          ; tmsWaitReg: Not sure how much delay we need so make a macro for now
    15                          ; -----------------------------------------------------------------------------
    16                          !macro tmsWaitReg {
    17                                  jsr _tmsWaitReg
    18                          }
    19                          
    20                          ; -----------------------------------------------------------------------------
    21                          ; tmsWaitData: Not sure how much delay we need so make a macro for now
    22                          ; -----------------------------------------------------------------------------
    23                          !macro tmsWaitData {
    24                                  jsr _tmsWaitData
    25                          }
    26                          
    27                          ; -----------------------------------------------------------------------------
    28                          ; tmsSetAddressWrite: Set an address in the TMS9918
    29                          ; -----------------------------------------------------------------------------
    30                          !macro tmsSetAddressWrite .addr {
    31                                  +tmsSetAddressRead ($4000 | .addr)
    32                          }
    33                          
    34                          ; -----------------------------------------------------------------------------
    35                          ; tmsSetAddressRead: Set an address to read from the TMS9918
    36                          ; -----------------------------------------------------------------------------
    37                          !macro tmsSetAddressRead .addr {
    38                                  php
    39                                  sei             ; we can't be interrupted here
    40                                  lda #<(.addr)
    41                                  sta TMS9918_REG
    42                                  +tmsWaitReg
    43                                  lda #>(.addr)
    44                                  sta TMS9918_REG
    45                                  +tmsWaitReg
    46                                  plp
    47                          }
    48                          
    49                          ; -----------------------------------------------------------------------------
    50                          ; tmsGet: Get a byte of data from the TMS9918
    51                          ; -----------------------------------------------------------------------------
    52                          !macro tmsGet {
    53                                  lda TMS9918_RAM
    54                                  +tmsWaitData
    55                          }
    56                          
    57                          ; -----------------------------------------------------------------------------
    58                          ; tmsPut: Send a byte of data to the TMS9918
    59                          ; -----------------------------------------------------------------------------
    60                          !macro tmsPut .byte {
    61                                  lda #(.byte & 0xff)
    62                                  +tmsPut
    63                          }
    64                          
    65                          
    66                          ; -----------------------------------------------------------------------------
    67                          ; tmsPut: Send a byte (A) of data to the TMS9918
    68                          ; -----------------------------------------------------------------------------
    69                          !macro tmsPut {
    70                                  sta TMS9918_RAM
    71                                  +tmsWaitData
    72                          }
    73                          
    74                          ; -----------------------------------------------------------------------------
    75                          ; tmsSetColor: Set current fg/bg color
    76                          ; -----------------------------------------------------------------------------
    77                          !macro tmsSetColor .color {
    78                                  lda #.color
    79                                  jsr tmsSetBackground
    80                          }
    81                          
    82                          ; -----------------------------------------------------------------------------
    83                          ; tmsSetColorFgBg: Set current fg/bg color
    84                          ; -----------------------------------------------------------------------------
    85                          !macro tmsSetColorFgBg .fg, .bg {
    86                                  +tmsColorFgBg .fg, .bg
    87                                  jsr tmsSetBackground
    88                          }
    89                          
    90                          ; -----------------------------------------------------------------------------
    91                          ; byteTmsColorFgBg: Output a data byte
    92                          ; -----------------------------------------------------------------------------
    93                          !macro byteTmsColorFgBg .fg, .bg {
    94                          !byte (.fg << 4 | .bg)
    95                          }
    96                          
    97                          
    98                          ; -----------------------------------------------------------------------------
    99                          ; tmsDisableOutput: Disable the TMS9918 output
   100                          ; -----------------------------------------------------------------------------
   101                          !macro tmsDisableOutput {
   102                                  lda #TMS_R1_DISP_ACTIVE
   103                                  jsr tmsReg1ClearFields
   104                          }
   105                          
   106                          ; -----------------------------------------------------------------------------
   107                          ; tmsEnableOutput: Enable the TMS9918 output
   108                          ; -----------------------------------------------------------------------------
   109                          !macro tmsEnableOutput {
   110                                  lda #TMS_R1_DISP_ACTIVE
   111                                  jsr tmsReg1SetFields
   112                          }
   113                          
   114                          ; -
   115                          !macro tmsEnableInterrupts {
   116                                  lda #TMS_R1_INT_ENABLE
   117                                  jsr tmsReg1SetFields
   118                          }
   119                          
   120                          !macro tmsDisableInterrupts {
   121                                  lda #TMS_R1_INT_ENABLE
   122                                  jsr tmsReg1ClearFields
   123                          }
   124                          
   125                          !macro tmsConsoleOut .char {
   126                                  lda #.char
   127                                  jsr tmsConsoleOut
   128                          }
   129                          
   130                          
   131                          ; -----------------------------------------------------------------------------
   132                          ; tmsConsolePrintAddr: Print text to console
   133                          ; -----------------------------------------------------------------------------
   134                          ; Inputs:
   135                          ;  textAddr: Address of null-terminated string to print
   136                          ; -----------------------------------------------------------------------------
   137                          !macro tmsConsolePrintAddr .textAddr {
   138                                  lda #<.textAddr
   139                                  sta STR_ADDR_L
   140                                  lda #>.textAddr
   141                                  sta STR_ADDR_H
   142                                  jsr tmsConsolePrint        
   143                          }
   144                          
   145                          ; -----------------------------------------------------------------------------
   146                          ; tmsConsolePrint: Print immediate text to console
   147                          ; -----------------------------------------------------------------------------
   148                          ; Inputs:
   149                          ;  str: String to print
   150                          ; -----------------------------------------------------------------------------
   151                          !macro tmsConsolePrint .str {
   152                          	jmp .afterText
   153                          .textAddr
   154                          	!text .str,0
   155                          .afterText        
   156                                  +tmsConsolePrintAddr .textAddr
   157                          }
   158                          
   159                          ; -----------------------------------------------------------------------------
   160                          ; +tmsColorFgBg: Set A to the given FG / BG color
   161                          ; -----------------------------------------------------------------------------
   162                          !macro tmsColorFgBg .fg, .bg {
   163                                  lda #(.fg << 4 | .bg)
   164                          }
   165                          
   166                          ; -----------------------------------------------------------------------------
   167                          ; tmsReadStatus: Read status - clear interrupt
   168                          ; -----------------------------------------------------------------------------
   169                          !macro tmsReadStatus  {
   170                                  bit TMS9918_REG
   171                          }
   172                          
   173                          ; -----------------------------------------------------------------------------
   174                          ; tmsSendData: Send # bytes from .sourceAddr to tms9918 data port
   175                          ; -----------------------------------------------------------------------------
   176                          !macro tmsSendData .sourceAddr, .numBytes {
   177                                  lda #<.sourceAddr
   178                                  sta TMS_TMP_ADDRESS
   179                                  lda #>.sourceAddr
   180                                  sta TMS_TMP_ADDRESS + 1
   181                          
   182                                  !if .numBytes < 256 {
   183                                          ldx #.numBytes
   184                                          jsr tmsSendBytes
   185                                  } else {
   186                                          !do while .numBytes > 0 {
   187                                                  !if .numBytes > 255 {
   188                                                          ldx #0
   189                                                          !set .numBytes = .numBytes - 256
   190                                                  } else {
   191                                                          ldx #.numBytes
   192                                                          !set .numBytes = 0
   193                                                  }
   194                                                  jsr tmsSendBytes
   195                                                  inc TMS_TMP_ADDRESS + 1
   196                                          }
   197                                  }
   198                          
   199                          }
   200                          
   201                          ; -----------------------------------------------------------------------------
   202                          ; tmsSendDataRpt: Send # bytes from .sourceAddr to tms9918 data port .rpt times
   203                          ; -----------------------------------------------------------------------------
   204                          !macro tmsSendDataRpt .sourceAddr, .numBytes, .rpt {
   205                                  lda #<.sourceAddr
   206                                  sta TMS_TMP_ADDRESS
   207                                  lda #>.sourceAddr
   208                                  sta TMS_TMP_ADDRESS + 1
   209                          
   210                                  !if .numBytes < 256 {
   211                                          !if .rpt < 5 {
   212                                                  !for i,1,.rpt {
   213                                                          ldx #.numBytes
   214                                                          jsr tmsSendBytes
   215                                                  }
   216                                          } else {
   217                                                  lda #.rpt
   218                                                  sta TMS9918_TMP_BUFFER
   219                          -
   220                                                  ldx #.numBytes
   221                                                  jsr tmsSendBytes
   222                                                  dec TMS9918_TMP_BUFFER
   223                                                  bne -
   224                                          }
   225                                  } else {
   226                                          !error "tmsSendDataRpt supports <256 bytes only"
   227                                  }
   228                          }
   229                          
   230                          
   231                          ; -----------------------------------------------------------------------------
   232                          ; tmsPutRpt: Send value .rpt times
   233                          ; -----------------------------------------------------------------------------
   234                          !macro tmsPutRpt .value, .rpt {
   235                                  ldx #.rpt
   236                                  lda #.value
   237                          -
   238                                  +tmsPut
   239                                  dex
   240                                  bne -
   241                          }
   242                          
   243                          !macro tmsPutSeq .from, .count {
   244                                  lda #.from
   245                          -
   246                                  +tmsPut
   247                                  inc
   248                                  cmp #<(.from + .count)
   249                                  bne -
   250                          }
   251                          
   252                          !macro tmsSetSourceAddressInd .addr {
   253                          	lda .addr
   254                          	sta TMS_TMP_ADDRESS
   255                          	lda .addr + 1
   256                          	sta TMS_TMP_ADDRESS + 1
   257                          }
   258                          
   259                          !macro tmsSetSourceAddressIndOffset .addr, .offset {
   260                                  clc
   261                          	lda .addr
   262                                  adc #<.offset
   263                          	sta TMS_TMP_ADDRESS
   264                          	lda .addr + 1
   265                                  adc #>.offset
   266                          	sta TMS_TMP_ADDRESS + 1
   267                          }
   268                          
   269                          
   270                          !macro tmsSendBytes .bytes {
   271                                  ldx #.bytes
   272                                  jsr tmsSendBytes
   273                          }
   274                          
   275                          
   276                          ; -----------------------------------------------------------------------------
   277                          ; tmsSetAddrPattTable: Initialise address for font table
   278                          ; -----------------------------------------------------------------------------
   279                          !macro tmsSetAddrPattTable {
   280                                  +tmsSetAddrPattTable 0
   281                          }
   282                          
   283                          ; -----------------------------------------------------------------------------
   284                          ; tmsSetAddrPattTable: Initialise address for pattern table
   285                          ; -----------------------------------------------------------------------------
   286                          !macro tmsSetAddrPattTable .ind {
   287                                  +tmsSetAddressWrite TMS_VRAM_PATT_ADDRESS + (8 * .ind)
   288                          }
   289                          
   290                          ; -----------------------------------------------------------------------------
   291                          ; tmsSetAddrPattTable: Initialise address for pattern table
   292                          ; -----------------------------------------------------------------------------
   293                          !macro tmsSetAddrPattTable .ind, .row {
   294                                  +tmsSetAddressWrite TMS_VRAM_PATT_ADDRESS + (8 * .ind) + .row
   295                          }
   296                          
   297                          ; -----------------------------------------------------------------------------
   298                          ; tmsSetAddrPattTableIIBank0: Initialise address for pattern table
   299                          ; -----------------------------------------------------------------------------
   300                          !macro tmsSetAddrPattTableIIBank0 .ind {
   301                                  +tmsSetAddrPattTable .ind
   302                          }
   303                          
   304                          ; -----------------------------------------------------------------------------
   305                          ; tmsSetAddrPattTableIIBank1: Initialise address for pattern table
   306                          ; -----------------------------------------------------------------------------
   307                          !macro tmsSetAddrPattTableIIBank1 .ind {
   308                                  +tmsSetAddrPattTable 256 + .ind
   309                          }
   310                          
   311                          ; -----------------------------------------------------------------------------
   312                          ; tmsSetAddrPattTableIIBank2: Initialise address for pattern table
   313                          ; -----------------------------------------------------------------------------
   314                          !macro tmsSetAddrPattTableIIBank2 .ind {
   315                                  +tmsSetAddrPattTable 512 + .ind
   316                          }
   317                          
   318                          ; -----------------------------------------------------------------------------
   319                          ; tmsSetAddrPattTableRead: Initialise address for pattern table to read
   320                          ; -----------------------------------------------------------------------------
   321                          !macro tmsSetAddrPattTableRead .ind {
   322                                  +tmsSetAddressRead TMS_VRAM_PATT_ADDRESS + (8 * .ind)
   323                          }
   324                          
   325                          ; -----------------------------------------------------------------------------
   326                          ; tmsSetAddrPattTableRowRead: Initialise address for pattern table to read
   327                          ; -----------------------------------------------------------------------------
   328                          !macro tmsSetAddrPattTableRead .ind, .row {
   329                                  +tmsSetAddressRead TMS_VRAM_PATT_ADDRESS + (8 * .ind) + .row
   330                          }
   331                          
   332                          ; -----------------------------------------------------------------------------
   333                          ; tmsUpdateFont: Update the pattern table with a given font
   334                          ; -----------------------------------------------------------------------------
   335                          !macro tmsUpdateFont .fontAddr {
   336                                  +tmsSetAddrPattTable 32
   337                                  +tmsSendData .fontAddr, $300
   338                          }
   339                          
   340                          ; -----------------------------------------------------------------------------
   341                          ; tmsSetAddrNameTable: Initialise address for base (text) table
   342                          ; -----------------------------------------------------------------------------
   343                          !macro tmsSetAddrNameTable {
   344                                  +tmsSetAddressWrite TMS_VRAM_NAME_ADDRESS
   345                          }
   346                          
   347                          ; -----------------------------------------------------------------------------
   348                          ; tmsSetAddrColorTable: Initialise address for color table
   349                          ; -----------------------------------------------------------------------------
   350                          !macro tmsSetAddrColorTable {
   351                                  +tmsSetAddressWrite TMS_VRAM_COLOR_ADDRESS
   352                          }
   353                          
   354                          ; -----------------------------------------------------------------------------
   355                          ; tmsSetAddrColorTable: Initialise address for color table index
   356                          ; -----------------------------------------------------------------------------
   357                          !macro tmsSetAddrColorTable .ind {
   358                                  +tmsSetAddressWrite TMS_VRAM_COLOR_ADDRESS + .ind
   359                          }
   360                          
   361                          ; -----------------------------------------------------------------------------
   362                          ; tmsSetAddrColorTableII: Initialise address for color table index (mode II)
   363                          ; -----------------------------------------------------------------------------
   364                          !macro tmsSetAddrColorTableII .ind {
   365                                  +tmsSetAddressWrite TMS_VRAM_COLOR_ADDRESS + .ind * 8
   366                          }
   367                          
   368                          ; -----------------------------------------------------------------------------
   369                          ; tmsSetAddrColorTableIIBank0: Initialise address for color table index (mode II)
   370                          ; -----------------------------------------------------------------------------
   371                          !macro tmsSetAddrColorTableIIBank0 .ind {
   372                                  +tmsSetAddrColorTableII .ind
   373                          }
   374                          
   375                          ; -----------------------------------------------------------------------------
   376                          ; tmsSetAddrColorTableIIBank1: Initialise address for color table index (mode II)
   377                          ; -----------------------------------------------------------------------------
   378                          !macro tmsSetAddrColorTableIIBank1 .ind {
   379                                  +tmsSetAddrColorTableII 256 + .ind
   380                          }
   381                          
   382                          ; -----------------------------------------------------------------------------
   383                          ; tmsSetAddrColorTableIIBank2: Initialise address for color table index (mode II)
   384                          ; -----------------------------------------------------------------------------
   385                          !macro tmsSetAddrColorTableIIBank2 .ind {
   386                                  +tmsSetAddrColorTableII 512 + .ind
   387                          }
   388                          
   389                          ; -----------------------------------------------------------------------------
   390                          ; tmsSetAddrSpriteAttrTable: Initialise address for sprite attributes table
   391                          ; -----------------------------------------------------------------------------
   392                          !macro tmsSetAddrSpriteAttrTable {
   393                                  +tmsSetAddrSpriteAttrTable 0
   394                          }
   395                          
   396                          ; -----------------------------------------------------------------------------
   397                          ; tmsSetAddrSpriteAttrTable: Initialise address for sprite attributes table
   398                          ; -----------------------------------------------------------------------------
   399                          !macro tmsSetAddrSpriteAttrTable .index {
   400                                  +tmsSetAddressWrite TMS_VRAM_SPRITE_ATTR_ADDRESS + .index * 4
   401                          }
   402                          
   403                          ; -----------------------------------------------------------------------------
   404                          ; tmsSetAddrSpritePattTable: Initialise address for sprite pattern table
   405                          ; -----------------------------------------------------------------------------
   406                          !macro tmsSetAddrSpritePattTable {
   407                                  +tmsSetAddrSpritePattTable 0
   408                          }
   409                          
   410                          ; -----------------------------------------------------------------------------
   411                          ; tmsSetAddrSpritePattTable: Initialise address for sprite pattern table
   412                          ; -----------------------------------------------------------------------------
   413                          !macro tmsSetAddrSpritePattTable .index {
   414                                  +tmsSetAddressWrite TMS_VRAM_SPRITE_PATT_ADDRESS + .index * 8
   415                          }
   416                          
   417                          
   418                          ; -----------------------------------------------------------------------------
   419                          ; tmsCreateSpritePattern: Create a sprite pattern (.spriteDataAddr is 8 bytes)
   420                          ; -----------------------------------------------------------------------------
   421                          !macro tmsCreateSpritePattern .pattInd, .spriteDataAddr {
   422                          
   423                                  
   424                          
   425                                  ; sprite pattern table
   426                                  +tmsSetAddrSpritePattTable .pattInd
   427                          
   428                                  ldx #0
   429                          -
   430                                  lda .spriteDataAddr,x
   431                                  +tmsPut
   432                                  inx
   433                                  cpx #8
   434                          
   435                                  
   436                          
   437                                  bne -
   438                          }
   439                          
   440                          ; -----------------------------------------------------------------------------
   441                          ; tmsCreateSpritePatternQuad: Create a (size 1) sprite pattern 
   442                          ;   (.spriteDataAddr is 32 bytes)
   443                          ; -----------------------------------------------------------------------------
   444                          !macro tmsCreateSpritePatternQuad .pattInd, .spriteDataAddr {
   445                          
   446                                  
   447                          
   448                                  ; sprite pattern table
   449                                  +tmsSetAddrSpritePattTable .pattInd * 4
   450                          
   451                                  ldx #0
   452                          -
   453                                  lda .spriteDataAddr,x
   454                                  +tmsPut 
   455                                  inx
   456                                  cpx #32
   457                          
   458                                  
   459                          
   460                                  bne -
   461                          }
   462                          
   463                          
   464                          !macro tmsCreateSpritePatternImm .ind, .b0, .b1, .b2, .b3, .b4, .b5, .b6, .b7 {
   465                          
   466                                  ; sprite pattern table
   467                                  +tmsSetAddrSpritePattTable .ind
   468                                  +tmsPut .b0
   469                                  +tmsPut .b2
   470                                  +tmsPut .b2
   471                                  +tmsPut .b3
   472                                  +tmsPut .b4
   473                                  +tmsPut .b5
   474                                  +tmsPut .b6
   475                                  +tmsPut .b7
   476                          }
   477                          
   478                          !macro tmsCreatePatternImm .ind, .b0, .b1, .b2, .b3, .b4, .b5, .b6, .b7 {
   479                          
   480                                  ; sprite pattern table
   481                                  +tmsSetAddrPattTable .ind
   482                                  +tmsPut .b0
   483                                  +tmsPut .b2
   484                                  +tmsPut .b2
   485                                  +tmsPut .b3
   486                                  +tmsPut .b4
   487                                  +tmsPut .b5
   488                                  +tmsPut .b6
   489                                  +tmsPut .b7
   490                          }
   491                          
   492                          
   493                          ; -----------------------------------------------------------------------------
   494                          ; tmsCreateSprite: Create a sprite
   495                          ; -----------------------------------------------------------------------------
   496                          !macro tmsCreateSprite .ind, .pattInd, .xPos, .yPos, .color {
   497                          
   498                                  ; sprite attr table
   499                                  +tmsSetAddrSpriteAttrTable .ind
   500                          
   501                                  +tmsPut .yPos
   502                                  +tmsPut .xPos
   503                                  +tmsPut .pattInd
   504                                  +tmsPut .color
   505                          }
   506                          
   507                          ; -----------------------------------------------------------------------------
   508                          ; tmsSpritePos: Set a sprite position
   509                          ; -----------------------------------------------------------------------------
   510                          !macro tmsSpritePos .ind, .xPos, .yPos {
   511                                  
   512                          
   513                                  ; sprite attr table
   514                                  +tmsSetAddrSpriteAttrTable .ind
   515                          
   516                                  +tmsPut .yPos
   517                                  +tmsPut .xPos        
   518                          }
   519                          
   520                          
   521                          ; -----------------------------------------------------------------------------
   522                          ; tmsSetLastSprite: Mark a sprite as the last sprite (set next ypos to )
   523                          ; -----------------------------------------------------------------------------
   524                          !macro tmsSetLastSprite .ind {
   525                                  +tmsSpritePos .ind + 1, 0, $d0
   526                          }
   527                          
   528                          
   529                          ; -----------------------------------------------------------------------------
   530                          ; tmsSpritePosXYReg: Set a sprite position from x/y registers
   531                          ; -----------------------------------------------------------------------------
   532                          !macro tmsSpritePosXYReg .ind {
   533                                  
   534                          
   535                                  ; sprite attr table
   536                                  +tmsSetAddrSpriteAttrTable .ind
   537                          
   538                                  tya
   539                                  +tmsPut 
   540                                  txa
   541                                  +tmsPut 
   542                          }
   543                          
   544                          
   545                          ; -----------------------------------------------------------------------------
   546                          ; tmsSetAddrSpriteColor: Change a sprite color
   547                          ; -----------------------------------------------------------------------------
   548                          !macro tmsSetAddrSpriteColor .ind {
   549                          
   550                                  ; sprite attr table
   551                                  +tmsSetAddressWrite TMS_VRAM_SPRITE_ATTR_ADDRESS + (.ind * 4) + 3
   552                          }
   553                          ; -----------------------------------------------------------------------------
   554                          ; tmsSpriteColor: Change a sprite color
   555                          ; -----------------------------------------------------------------------------
   556                          !macro tmsSpriteColor .ind, .color {
   557                          
   558                                  +tmsSetAddrSpriteColor .ind
   559                          
   560                                  +tmsPut .color
   561                          }
   562                          
   563                          
   564                          ; -----------------------------------------------------------------------------
   565                          ; tmsSetPosWrite: Set cursor position
   566                          ; -----------------------------------------------------------------------------
   567                          !macro tmsSetPosWrite .x, .y {
   568                                  +tmsSetAddressWrite (TMS_VRAM_NAME_ADDRESS + .y * 32 + .x)
   569                          }
   570                          
   571                          ; -----------------------------------------------------------------------------
   572                          ; tmsSetPosRead: Set read cursor position
   573                          ; -----------------------------------------------------------------------------
   574                          !macro tmsSetPosRead .x, .y {
   575                                  +tmsSetAddressRead (TMS_VRAM_NAME_ADDRESS + .y * 32 + .x)
   576                          }
   577                          
   578                          ; -----------------------------------------------------------------------------
   579                          ; tmsPrint: Print immediate text
   580                          ; -----------------------------------------------------------------------------
   581                          ; Inputs:
   582                          ;  str: String to print
   583                          ;  x: x position
   584                          ;  y: y position
   585                          ; -----------------------------------------------------------------------------
   586                          !macro tmsPrint .str, .x, .y {
   587                          	jmp .afterText
   588                          .textAddr
   589                          	!text .str,0
   590                          .afterText        
   591                          
   592                                  +tmsSetPosWrite .x, .y
   593                          
   594                                  lda #<.textAddr
   595                                  sta STR_ADDR_L
   596                                  lda #>.textAddr
   597                                  sta STR_ADDR_H
   598                                  jsr tmsPrint        
   599                          }
   600                          
   601                          
   602                          ; -----------------------------------------------------------------------------
   603                          ; tmsPrintCentre: Print centre-aligned immediate text
   604                          ; -----------------------------------------------------------------------------
   605                          ; Inputs:
   606                          ;  str: String to print
   607                          ;  y: y position
   608                          ; -----------------------------------------------------------------------------
   609                          !macro tmsPrintCentre .str, .y {
   610                          	jmp .afterText
   611                          .textAddr
   612                          	!text .str,0
   613                          .afterText        
   614                          
   615                                  +tmsSetPosWrite (32 - ((.afterText - 1) - .textAddr)) / 2, .y
   616                          
   617                                  lda #<.textAddr
   618                                  sta STR_ADDR_L
   619                                  lda #>.textAddr
   620                                  sta STR_ADDR_H
   621                                  jsr tmsPrint        
   622                          }
   623                          
   624                          
   625                          ; -----------------------------------------------------------------------------
   626                          ; tmsPrintZ: Print text
   627                          ; -----------------------------------------------------------------------------
   628                          ; Inputs:
   629                          ;  str: Address of zero-terminated string to print
   630                          ;  x: x position
   631                          ;  y: y position
   632                          ; -----------------------------------------------------------------------------
   633                          !macro tmsPrintZ .textAddr, .x, .y {
   634                                  +tmsSetPosWrite .x, .y
   635                          
   636                                  lda #<.textAddr
   637                                  sta STR_ADDR_L
   638                                  lda #>.textAddr
   639                                  sta STR_ADDR_H
   640                                  jsr tmsPrint        
   641                          }

; ******** Source: ../kernel\hbc56kernel.inc
    19                          

; ******** Source: ../lib\gfx\tilemap.inc
     1                          ; 6502 - Tilemap
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          ;
    10                          
    11                          
    12                          
    13                          !macro tilemapCreate .tilemapStructAddr, .bufferAddr, .tilesetAddr, .sizeFlags, .tileSizePx, .invertAddr, .dirtyAddr {
    14                          	!if <.tilesetAddr != 0 { !error "tilemapCreate: Tileset address must be page-aligned",.tilesetAddr }
    15                          	!if >.tilesetAddr < 3 { !error "tilemapCreate: Tileset address must be greater than $2ff",.tilesetAddr }
    16                          	!if <.bufferAddr != 0 { !error "tilemapCreate: Buffer address must be page-aligned",.bufferAddr }
    17                          	!if >.bufferAddr < 3 { !error "tilemapCreate: Buffer address must be greater than $2ff",.bufferAddr }
    18                          	!if .invertAddr != 0 and <.invertAddr != 0  {!error "tilemapCreate: Invert address must be page-aligned", .invertAddr}
    19                          	!if .invertAddr != 0 and >.invertAddr < 3  {!error "tilemapCreate: Invert address must be greater than $2ff", .invertAddr}
    20                          	!if .dirtyAddr != 0 and <.dirtyAddr != 0  {!error "tilemapCreate: Dirty address must be page-aligned", .dirtyAddr}
    21                          	!if .dirtyAddr != 0 and >.dirtyAddr < 3  {!error "tilemapCreate: Dirty address must be greater than $2ff", .dirtyAddr}
    22                          	!if .tileSizePx != 4 and .tileSizePx != 8 {!error "tilemapCreate: Tile size must be 4 or 8 pixels",.tileSizePx}
    23                          
    24                          	lda #<.tilemapStructAddr
    25                          	sta TILEMAP_ADDR
    26                          	lda #>.tilemapStructAddr
    27                          	sta TILEMAP_ADDR + 1
    28                          
    29                          	lda #>.bufferAddr
    30                          	sta .tilemapStructAddr + TILEMAP_BUFFER_ADDR
    31                          	lda #.sizeFlags
    32                          	sta .tilemapStructAddr + TILEMAP_SIZE
    33                          	lda #>.tilesetAddr
    34                          	sta .tilemapStructAddr + TILEMAP_TILES_ADDR
    35                          	lda #>.invertAddr
    36                          	sta .tilemapStructAddr + TILEMAP_INVERT_ADDR
    37                          	lda #>.dirtyAddr
    38                          	sta .tilemapStructAddr + TILEMAP_DIRTY_ADDR
    39                          	lda #.tileSizePx
    40                          	sta .tilemapStructAddr + TILEMAP_TILE_SIZE_PX
    41                          
    42                          	jsr tilemapInit
    43                          }
    44                          
    45                          !macro tilemapCreateDefault .sizeFlags, .tilesetAddr {
    46                          	+tilemapCreate TILEMAP_FIXED_ADDRESS, TILEMAP_DEFAULT_BUFFER_ADDRESS, .tilesetAddr, .sizeFlags, 8, $0, $0
    47                          }
    48                          
    49                          !macro tilemapSetActive .tilemapStructAddr {
    50                          	lda #<.tilemapStructAddr
    51                          	sta TILEMAP_ADDR
    52                          	lda #>.tilemapStructAddr
    53                          	sta TILEMAP_ADDR + 1
    54                          
    55                          	jsr tilemapSetActive

; ******** Source: ../kernel\hbc56kernel.inc
    20                          

; ******** Source: ../lib\lcd\lcd.inc
     1                          ; 6502 LCD Macros - HBC-56
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          
    10                          ; -----------------------------------------------------------------------------
    11                          ; lcdPrint: Print immediate text
    12                          ; -----------------------------------------------------------------------------
    13                          ; Inputs:
    14                          ;  str: String to print
    15                          ; -----------------------------------------------------------------------------
    16                          !macro lcdPrint str {
    17                          	jmp +
    18                          .textAddr
    19                          	!text str,0
    20                          +
    21                          	lda #<.textAddr
    22                          	sta STR_ADDR_L
    23                          	lda #>.textAddr
    24                          	sta STR_ADDR_H
    25                          	jsr lcdPrint
    26                          }
    27                          
    28                          
    29                          ; -----------------------------------------------------------------------------
    30                          ; lcdChar: Print immediate character
    31                          ; -----------------------------------------------------------------------------
    32                          ; Inputs:
    33                          ;  c: Character to print
    34                          ; -----------------------------------------------------------------------------
    35                          !macro lcdChar c {
    36                          	pha
    37                          	lda #c
    38                          	jsr lcdChar
    39                          	pla
    40                          }
    41                          
    42                          
    43                          ; -----------------------------------------------------------------------------
    44                          ; lcdConsolePrint: Print immediate text to console
    45                          ; -----------------------------------------------------------------------------
    46                          ; Inputs:
    47                          ;  str: String to print
    48                          ; -----------------------------------------------------------------------------
    49                          !macro lcdConsolePrint .str {
    50                          	jmp .afterText
    51                          .textAddr
    52                          	!text .str,0
    53                          .afterText        
    54                          
    55                                  lda #<.textAddr
    56                                  sta STR_ADDR_L
    57                                  lda #>.textAddr
    58                                  sta STR_ADDR_H
    59                                  jsr lcdConsolePrint        

; ******** Source: ../kernel\hbc56kernel.inc
    21                          

; ******** Source: ../lib\inp\nes.inc
     1                          ; 6502 NES Controller Macros - HBC-56
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          ; Dependencies:
    10                          ;  - hbc56.asm
    11                          
    12                          
    13                          !macro nes1BranchIfPressed .buttonMask, .addr {
    14                                  pha
    15                                  lda #(.buttonMask)
    16                                  jsr nes1Pressed
    17                                  pla
    18                                  bcs .addr
    19                          }
    20                          
    21                          !macro nes1BranchIfNotPressed .buttonMask, .addr {
    22                                  pha
    23                                  lda #(.buttonMask)
    24                                  jsr nes1Pressed
    25                                  pla
    26                                  bcc .addr
    27                          }
    28                          
    29                          !macro nes2BranchIfPressed .buttonMask, addr {
    30                                  pha
    31                                  lda #(.buttonMask)
    32                                  jsr nes2Pressed
    33                                  pla
    34                                  bcs addr
    35                          }
    36                          
    37                          !macro nes2BranchIfNotPressed .buttonMask, addr {
    38                                  pha
    39                                  lda #(.buttonMask)
    40                                  jsr nes2Pressed
    41                                  pla
    42                                  bcc addr
    43                          }

; ******** Source: ../kernel\hbc56kernel.inc
    22                          

; ******** Source: ../lib\inp\keyboard.inc
     1                          ; 6502 KB Controller Macros - HBC-56
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          ; Dependencies:
    10                          ;  - hbc56.asm
    11                          
    12                          
    13                          !macro kbBranchIfNotPressed .scancode, .addr {
    14                                  ldx #.scancode
    15                                  jsr kbReadAscii
    16                                  beq .addr
    17                          }
    18                          
    19                          !macro kbBranchIfPressed .scancode, .addr {
    20                                  ldx #.scancode
    21                                  jsr kbIsPressed
    22                                  bne .addr
    23                          }
    24                          
    25                          !macro kbSetEventHandlerPressed .cb {
    26                                  lda #<.cb
    27                                  sta KB_CB_PRESSED
    28                                  lda #>.cb
    29                                  sta KB_CB_PRESSED + 1
    30                          }
    31                          
    32                          !macro kbSetEventHandlerReleased .cb {
    33                                  lda #<.cb
    34                                  sta KB_CB_RELEASED
    35                                  lda #>.cb
    36                                  sta KB_CB_RELEASED + 1

; ******** Source: ../kernel\hbc56kernel.inc
    23                          

; ******** Source: ../lib\sfx\ay3891x.inc
     1                          ; 6502 - AY-3-819x PSG
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          
    10                          
    11                          
    12                          !macro ayWrite .dev, .reg, .val {
    13                                  lda #.reg
    14                                  sta IO_PORT_BASE_ADDRESS | AY_IO_PORT | AY_ADDR | .dev
    15                                  lda #.val
    16                                  sta IO_PORT_BASE_ADDRESS | AY_IO_PORT | AY_WRITE | .dev
    17                          }        
    18                          
    19                          !macro ayRead .dev, .reg {
    20                                  lda #.reg
    21                                  sta IO_PORT_BASE_ADDRESS | AY_IO_PORT | AY_ADDR | .dev
    22                                  lda IO_PORT_BASE_ADDRESS | AY_IO_PORT | AY_READ | .dev
    23                          }        
    24                          
    25                          
    26                          !macro ayWriteX .dev, .reg {
    27                                  lda #.reg
    28                                  sta IO_PORT_BASE_ADDRESS | AY_IO_PORT | AY_ADDR | .dev
    29                                  stx IO_PORT_BASE_ADDRESS | AY_IO_PORT | AY_WRITE | .dev
    30                          }
    31                          
    32                          !macro ayWriteA .dev, .reg {
    33                                  ldx #.reg
    34                                  stx IO_PORT_BASE_ADDRESS | AY_IO_PORT | AY_ADDR | .dev
    35                                  sta IO_PORT_BASE_ADDRESS | AY_IO_PORT | AY_WRITE | .dev
    36                          }
    37                          
    38                          !macro ayPlayNote .dev, .chan, .freq {
    39                                  !if .freq <= 0 {
    40                                          .val = 0
    41                                  } else {
    42                                          .val = AY_CLOCK_FREQ / (32.0 * .freq)
    43                                  }
    44                                  +ayWrite .dev, AY_CHA_TONE_L + (.chan * 2), <.val
    45                                  +ayWrite .dev, AY_CHA_TONE_H + (.chan * 2), >.val
    46                          }
    47                          
    48                          !macro ayToneWord .freq {
    49                                  !word (AY_CLOCK_FREQ / (32.0 * .freq))
    50                          }
    51                          
    52                          !macro ayToneByteL .freq {
    53                                  !byte <(AY_CLOCK_FREQ / (32.0 * .freq))
    54                          }
    55                          
    56                          !macro ayToneByteH .freq {
    57                                  !byte >(AY_CLOCK_FREQ / (32.0 * .freq))
    58                          }
    59                          
    60                          
    61                          !macro ayToneEnable .dev, .chan {
    62                                  +ayRead .dev, AY_ENABLES
    63                                  and #!($01 << .chan)
    64                                  +ayWriteA .dev, AY_ENABLES
    65                          }
    66                          
    67                          !macro ayToneDisable .dev, .chan {
    68                                  +ayRead .dev, AY_ENABLES
    69                                  ora #($01 << .chan)
    70                                  +ayWriteA .dev, AY_ENABLES
    71                          }
    72                          
    73                          !macro ayNoiseEnable .dev, .chan {
    74                                  +ayRead .dev, AY_ENABLES
    75                                  eor #($08 << .chan)
    76                                  +ayWriteA .dev, AY_ENABLES
    77                          }
    78                          
    79                          !macro ayNoiseDisable .dev, .chan {
    80                                  +ayRead .dev, AY_ENABLES
    81                                  ora #($08 << .chan)
    82                                  +ayWriteA .dev, AY_ENABLES
    83                          }
    84                          
    85                          !macro aySetVolume .dev, .chan, .vol {
    86                                  +ayWrite .dev, (AY_CHA_AMPL + .chan), (.vol >> 4)
    87                          }
    88                          
    89                          !macro aySetVolumeEnvelope .dev, .chan {
    90                                  +ayWrite .dev, (AY_CHA_AMPL + .chan), $10
    91                          }
    92                          
    93                          !macro aySetEnvelopePeriod .dev, .period {
    94                                  +ayWrite .dev, AY_ENV_PERIOD_L, <.period
    95                                  +ayWrite .dev, AY_ENV_PERIOD_H, >.period
    96                          }
    97                          
    98                          !macro aySetEnvShape .dev, .shape {
    99                                  +ayWrite .dev, AY_ENV_SHAPE, .shape
   100                          }
   101                          
   102                          !macro aySetNoise .dev, .freq {
   103                                  +ayWrite .dev, AY_ENV_SHAPE, .freq >> 3
   104                          }
   105                          
   106                          !macro ayStop .dev, .chan {
   107                                  +ayPlayNote .dev, .chan, 0
   108                          }

; ******** Source: ../kernel\hbc56kernel.inc
    24                          

; ******** Source: ../lib\ser\uart.inc
     1                          ; 6502 - MC68B50 UART Macros
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          
    10                          ; -----------------------------------------------------------------------------
    11                          ; uartOutStringAddr: Output a string to the uart
    12                          ; -----------------------------------------------------------------------------
    13                          ; Inputs:
    14                          ;  .addr: Address of null-terminated string to print
    15                          ; -----------------------------------------------------------------------------
    16                          !macro uartOutStringAddr .addr {
    17                                  lda #<.addr
    18                                  sta STR_ADDR_L
    19                                  lda #>.addr
    20                                  sta STR_ADDR_H
    21                                  jsr uartOutString        
    22                          }
    23                          
    24                          
    25                          ; -----------------------------------------------------------------------------
    26                          ; uartOutString: Output an immediate string to the uart
    27                          ; -----------------------------------------------------------------------------
    28                          ; Inputs:
    29                          ;  .str: String to output
    30                          ; -----------------------------------------------------------------------------
    31                          !macro uartOutString .str {
    32                          	jmp @afterText
    33                          @textAddr
    34                          	!text .str,0
    35                          @afterText        
    36                                  +uartOutStringAddr @textAddr
    37                          }
    38                          

; ******** Source: ../kernel\hbc56kernel.inc
    25                          

; ******** Source: ../kernel\kernel.inc
     1                          ; 6502 - HBC-56 Kernel Macros
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          ;
    10                          
    11                          !macro setIntHandler .address {
    12                                  lda #<.address
    13                                  sta HBC56_INT_VECTOR + 1
    14                                  lda #>.address
    15                                  sta HBC56_INT_VECTOR + 2
    16                                  lda #JMP_OPCODE
    17                                  sta HBC56_INT_VECTOR
    18                          }
    19                          
    20                          !macro setNmiHandler .address {
    21                                  lda #<.address
    22                                  sta HBC56_NMI_VECTOR + 1
    23                                  lda #>.address
    24                                  sta HBC56_NMI_VECTOR + 2
    25                                  lda #JMP_OPCODE
    26                                  sta HBC56_NMI_VECTOR
    27                          }
    28                          
    29                          !macro setHbcMetaNES {
    30                                  lda #HBC56_CONSOLE_FLAG_NES
    31                                  ora HBC56_CONSOLE_FLAGS
    32                                  sta HBC56_CONSOLE_FLAGS
    33                          }
    34                          
    35                          !macro setHbcMetaNoWait {
    36                                  lda #HBC56_CONSOLE_FLAG_NOWAIT
    37                                  ora HBC56_CONSOLE_FLAGS
    38                                  sta HBC56_CONSOLE_FLAGS
    39                          }
    40                          
    41                          
    42                          !macro hbc56SetVsyncCallback .vsync {
    43                                  lda #<.vsync
    44                                  sta HBC56_VSYNC_CALLBACK
    45                                  lda #>.vsync
    46                                  sta HBC56_VSYNC_CALLBACK + 1
    47                          }
    48                          
    49                          !macro hbc56SetViaCallback .cb {
    50                                  lda #<.cb
    51                                  sta HBC56_VIA_CALLBACK
    52                                  lda #>.cb
    53                                  sta HBC56_VIA_CALLBACK + 1
    54                          }
    55                          
    56                          
    57                          !macro setHbcMetaTitle .titleStr {
    58                                  jmp .hbcMetaTitleOut
    59                          .titleStrLabel:
    60                                  !text .titleStr
    61                          .titleStrLabelLen = * - .titleStrLabel
    62                                  !byte 0 ; nul terminator for game name
    63                          
    64                          !if .titleStrLabelLen > HBC56_META_TITLE_MAX_LEN {
    65                                  !error "setHbcMetaTitle: Title metadata limited to ",HBC56_META_TITLE_MAX_LEN,"bytes"
    66                          }
    67                          .hbcMetaTitleOut:
    68                                  +memcpy HBC56_META_TITLE + (HBC56_META_TITLE_MAX_LEN-.titleStrLabelLen)/2, .titleStrLabel, .titleStrLabelLen
    69                                  lda #.titleStrLabelLen
    70                                  sta HBC56_META_TITLE_LEN
    71                          }
    72                          
    73                          !macro consoleEnableCursor {
    74                                  lda HBC56_CONSOLE_FLAGS
    75                                  ora #HBC56_CONSOLE_FLAG_CURSOR
    76                                  sta HBC56_CONSOLE_FLAGS
    77                          }
    78                          
    79                          !macro consoleDisableCursor {
    80                                  lda HBC56_CONSOLE_FLAGS
    81                                  and #!HBC56_CONSOLE_FLAG_CURSOR & $ff
    82                                  sta HBC56_CONSOLE_FLAGS
    83                          }
    84                          
    85                          !macro consoleLCDMode {
    86                                  lda HBC56_CONSOLE_FLAGS
    87                                  ora #HBC56_CONSOLE_FLAG_LCD
    88                                  sta HBC56_CONSOLE_FLAGS
    89                          }
    90                          
    91                          !macro setBreakpoint {
    92                                 !byte $db 
    93                          }
    94                          
    95                          !macro hbc56CustomDelay .delay {
    96                                  ldy #.delay
    97                                  jsr hbc56CustomDelay
    98                          }
    99                          
   100                          !macro hbc56DelayUs .us {
   101                          !if .us = 1 {
   102                                  nop
   103                                  nop
   104                          }
   105                          }
   106                          !macro hbc56DelayMs .ms {
   107                                  lda #<.ms
   108                                  sta DELAY_L
   109                                  lda #>.ms
   110                                  sta DELAY_H
   111                          
   112                                  jsr hbc56CustomDelayMs

; ******** Source: ../kernel\hbc56kernel.inc
    26                          
    27                          
    28                          !ifndef HBC_56_EXCLUDE_KERNEL_ROM {
    29                          
    30                                  ; if the program requires the kernal image
    31                                  ; then... include it
    32                          
    33                                  *=HBC56_META_VECTOR
    34                                  !ifdef hbc56Meta {
    35  dffc 4c03ca                             jmp hbc56Meta
    36                                  } else {
    37                                          rts
    38                                  }
    39                          
    40                                  *=HBC56_KERNEL_START
    41  e000 c9619005c97b9002...        !bin "kernel.o"
    42                          
    43                                  *=DEFAULT_HBC56_RST_VECTOR
    44  8000 4c7bb8                     jmp hbc56Main
    45                          
    46                          } else {
    47                          
    48                                  ; otherwise, place the program in RAM
    49                          
    50                                  *=$0400

; ******** Source: basic_hbc56_core.asm
    11                          

; ******** Source: ehbasic\basic.asm
     1                          
     2                          ; Enhanced BASIC to assemble under 6502 simulator, $ver 2.22
     3                          
     4                          ; $E7E1 $E7CF $E7C6 $E7D3 $E7D1 $E7D5 $E7CF $E81E $E825
     5                          
     6                          ; 2.00	new revision numbers start here
     7                          ; 2.01	fixed LCASE$() and UCASE$()
     8                          ; 2.02	new get value routine done
     9                          ; 2.03	changed RND() to galoise method
    10                          ; 2.04	fixed SPC()
    11                          ; 2.05	new get value routine fixed
    12                          ; 2.06	changed USR() code
    13                          ; 2.07	fixed STR$()
    14                          ; 2.08	changed INPUT and READ to remove need for $00 start to input buffer
    15                          ; 2.09	fixed RND()
    16                          ; 2.10	integrated missed changes from an earlier version
    17                          ; 2.20	added ELSE to IF .. THEN and fixed IF .. GOTO <statement> to cause error
    18                          ; 2.21	fixed IF .. THEN RETURN to not cause error
    19                          ; 2.22	fixed RND() breaking the get byte routine
    20                          
    21                          ; zero page use ..
    22                          
    23                          LAB_WARM 		= $00		; BASIC warm start entry point
    24                          Wrmjpl 		= LAB_WARM+1; BASIC warm start vector jump low byte
    25                          Wrmjph 		= LAB_WARM+2; BASIC warm start vector jump high byte
    26                          
    27                          Usrjmp		= $0A		; USR function JMP address
    28                          Usrjpl		= Usrjmp+1	; USR function JMP vector low byte
    29                          Usrjph		= Usrjmp+2	; USR function JMP vector high byte
    30                          Nullct		= $0D		; nulls output after each line
    31                          TPos			= $0E		; BASIC terminal position byte
    32                          TWidth		= $0F		; BASIC terminal width byte
    33                          Iclim			= $10		; input column limit
    34                          Itempl		= $11		; temporary integer low byte
    35                          Itemph		= Itempl+1	; temporary integer high byte
    36                          
    37                          nums_1		= Itempl	; number to bin/hex string convert MSB
    38                          nums_2		= nums_1+1	; number to bin/hex string convert
    39                          nums_3		= nums_1+2	; number to bin/hex string convert LSB
    40                          
    41                          Srchc			= $5B		; search character
    42                          Temp3			= Srchc	; temp byte used in number routines
    43                          Scnquo		= $5C		; scan-between-quotes flag
    44                          Asrch			= Scnquo	; alt search character
    45                          
    46                          XOAw_l		= Srchc	; eXclusive OR, OR and AND word low byte
    47                          XOAw_h		= Scnquo	; eXclusive OR, OR and AND word high byte
    48                          
    49                          Ibptr			= $5D		; input buffer pointer
    50                          Dimcnt		= Ibptr	; # of dimensions
    51                          Tindx			= Ibptr	; token index
    52                          
    53                          Defdim		= $5E		; default DIM flag
    54                          Dtypef		= $5F		; data type flag, $FF=string, $00=numeric
    55                          Oquote		= $60		; open quote flag (b7) (Flag: DATA scan; LIST quote; memory)
    56                          Gclctd		= $60		; garbage collected flag
    57                          Sufnxf		= $61		; subscript/FNX flag, 1xxx xxx = FN(0xxx xxx)
    58                          Imode			= $62		; input mode flag, $00=INPUT, $80=READ
    59                          
    60                          Cflag			= $63		; comparison evaluation flag
    61                          
    62                          TabSiz		= $64		; TAB step size (was input flag)
    63                          
    64                          next_s		= $65		; next descriptor stack address
    65                          
    66                          					; these two bytes form a word pointer to the item
    67                          					; currently on top of the descriptor stack
    68                          last_sl		= $66		; last descriptor stack address low byte
    69                          last_sh		= $67		; last descriptor stack address high byte (always $00)
    70                          
    71                          des_sk		= $68		; descriptor stack start address (temp strings)
    72                          
    73                          ;			= $70		; End of descriptor stack
    74                          
    75                          ut1_pl		= $71		; utility pointer 1 low byte
    76                          ut1_ph		= ut1_pl+1	; utility pointer 1 high byte
    77                          ut2_pl		= $73		; utility pointer 2 low byte
    78                          ut2_ph		= ut2_pl+1	; utility pointer 2 high byte
    79                          
    80                          Temp_2		= ut1_pl	; temp byte for block move	
    81                          
    82                          FACt_1		= $75		; FAC temp mantissa1
    83                          FACt_2		= FACt_1+1	; FAC temp mantissa2
    84                          FACt_3		= FACt_2+1	; FAC temp mantissa3
    85                          
    86                          dims_l		= FACt_2	; array dimension size low byte
    87                          dims_h		= FACt_3	; array dimension size high byte
    88                          
    89                          TempB			= $78		; temp page 0 byte
    90                          
    91                          Smeml			= $79		; start of mem low byte		(Start-of-Basic)
    92                          Smemh			= Smeml+1	; start of mem high byte	(Start-of-Basic)
    93                          Svarl			= $7B		; start of vars low byte	(Start-of-Variables)
    94                          Svarh			= Svarl+1	; start of vars high byte	(Start-of-Variables)
    95                          Sarryl		= $7D		; var mem end low byte		(Start-of-Arrays)
    96                          Sarryh		= Sarryl+1	; var mem end high byte		(Start-of-Arrays)
    97                          Earryl		= $7F		; array mem end low byte	(End-of-Arrays)
    98                          Earryh		= Earryl+1	; array mem end high byte	(End-of-Arrays)
    99                          Sstorl		= $81		; string storage low byte	(String storage (moving down))
   100                          Sstorh		= Sstorl+1	; string storage high byte	(String storage (moving down))
   101                          Sutill		= $83		; string utility ptr low byte
   102                          Sutilh		= Sutill+1	; string utility ptr high byte
   103                          Ememl			= $85		; end of mem low byte		(Limit-of-memory)
   104                          Ememh			= Ememl+1	; end of mem high byte		(Limit-of-memory)
   105                          Clinel		= $87		; current line low byte		(Basic line number)
   106                          Clineh		= Clinel+1	; current line high byte	(Basic line number)
   107                          Blinel		= $89		; break line low byte		(Previous Basic line number)
   108                          Blineh		= Blinel+1	; break line high byte		(Previous Basic line number)
   109                          
   110                          Cpntrl		= $8B		; continue pointer low byte
   111                          Cpntrh		= Cpntrl+1	; continue pointer high byte
   112                          
   113                          Dlinel		= $8D		; current DATA line low byte
   114                          Dlineh		= Dlinel+1	; current DATA line high byte
   115                          
   116                          Dptrl			= $8F		; DATA pointer low byte
   117                          Dptrh			= Dptrl+1	; DATA pointer high byte
   118                          
   119                          Rdptrl		= $91		; read pointer low byte
   120                          Rdptrh		= Rdptrl+1	; read pointer high byte
   121                          
   122                          Varnm1		= $93		; current var name 1st byte
   123                          Varnm2		= Varnm1+1	; current var name 2nd byte
   124                          
   125                          Cvaral		= $95		; current var address low byte
   126                          Cvarah		= Cvaral+1	; current var address high byte
   127                          
   128                          Frnxtl		= $97		; var pointer for FOR/NEXT low byte
   129                          Frnxth		= Frnxtl+1	; var pointer for FOR/NEXT high byte
   130                          
   131                          Tidx1			= Frnxtl	; temp line index
   132                          
   133                          Lvarpl		= Frnxtl	; let var pointer low byte
   134                          Lvarph		= Frnxth	; let var pointer high byte
   135                          
   136                          prstk			= $99		; precedence stacked flag
   137                          
   138                          comp_f		= $9B		; compare function flag, bits 0,1 and 2 used
   139                          					; bit 2 set if >
   140                          					; bit 1 set if =
   141                          					; bit 0 set if <
   142                          
   143                          func_l		= $9C		; function pointer low byte
   144                          func_h		= func_l+1	; function pointer high byte
   145                          
   146                          garb_l		= func_l	; garbage collection working pointer low byte
   147                          garb_h		= func_h	; garbage collection working pointer high byte
   148                          
   149                          des_2l		= $9E		; string descriptor_2 pointer low byte
   150                          des_2h		= des_2l+1	; string descriptor_2 pointer high byte
   151                          
   152                          g_step		= $A0		; garbage collect step size
   153                          
   154                          Fnxjmp		= $A1		; jump vector for functions
   155                          Fnxjpl		= Fnxjmp+1	; functions jump vector low byte
   156                          Fnxjph		= Fnxjmp+2	; functions jump vector high byte
   157                          
   158                          g_indx		= Fnxjpl	; garbage collect temp index
   159                          
   160                          FAC2_r		= $A3		; FAC2 rounding byte
   161                          
   162                          Adatal		= $A4		; array data pointer low byte
   163                          Adatah		= Adatal+1	; array data pointer high  byte
   164                          
   165                          Nbendl		= Adatal	; new block end pointer low byte
   166                          Nbendh		= Adatah	; new block end pointer high  byte
   167                          
   168                          Obendl		= $A6		; old block end pointer low byte
   169                          Obendh		= Obendl+1	; old block end pointer high  byte
   170                          
   171                          numexp		= $A8		; string to float number exponent count
   172                          expcnt		= $A9		; string to float exponent count
   173                          
   174                          numbit		= numexp	; bit count for array element calculations
   175                          
   176                          numdpf		= $AA		; string to float decimal point flag
   177                          expneg		= $AB		; string to float eval exponent -ve flag
   178                          
   179                          Astrtl		= numdpf	; array start pointer low byte
   180                          Astrth		= expneg	; array start pointer high  byte
   181                          
   182                          Histrl		= numdpf	; highest string low byte
   183                          Histrh		= expneg	; highest string high  byte
   184                          
   185                          Baslnl		= numdpf	; BASIC search line pointer low byte
   186                          Baslnh		= expneg	; BASIC search line pointer high  byte
   187                          
   188                          Fvar_l		= numdpf	; find/found variable pointer low byte
   189                          Fvar_h		= expneg	; find/found variable pointer high  byte
   190                          
   191                          Ostrtl		= numdpf	; old block start pointer low byte
   192                          Ostrth		= expneg	; old block start pointer high  byte
   193                          
   194                          Vrschl		= numdpf	; variable search pointer low byte
   195                          Vrschh		= expneg	; variable search pointer high  byte
   196                          
   197                          FAC1_e		= $AC		; FAC1 exponent
   198                          FAC1_1		= FAC1_e+1	; FAC1 mantissa1
   199                          FAC1_2		= FAC1_e+2	; FAC1 mantissa2
   200                          FAC1_3		= FAC1_e+3	; FAC1 mantissa3
   201                          FAC1_s		= FAC1_e+4	; FAC1 sign (b7)
   202                          
   203                          str_ln		= FAC1_e	; string length
   204                          str_pl		= FAC1_1	; string pointer low byte
   205                          str_ph		= FAC1_2	; string pointer high byte
   206                          
   207                          des_pl		= FAC1_2	; string descriptor pointer low byte
   208                          des_ph		= FAC1_3	; string descriptor pointer high byte
   209                          
   210                          mids_l		= FAC1_3	; MID$ string temp length byte
   211                          
   212                          negnum		= $B1		; string to float eval -ve flag
   213                          numcon		= $B1		; series evaluation constant count
   214                          
   215                          FAC1_o		= $B2		; FAC1 overflow byte
   216                          
   217                          FAC2_e		= $B3		; FAC2 exponent
   218                          FAC2_1		= FAC2_e+1	; FAC2 mantissa1
   219                          FAC2_2		= FAC2_e+2	; FAC2 mantissa2
   220                          FAC2_3		= FAC2_e+3	; FAC2 mantissa3
   221                          FAC2_s		= FAC2_e+4	; FAC2 sign (b7)
   222                          
   223                          FAC_sc		= $B8		; FAC sign comparison, Acc#1 vs #2
   224                          FAC1_r		= $B9		; FAC1 rounding byte
   225                          
   226                          ssptr_l		= FAC_sc	; string start pointer low byte
   227                          ssptr_h		= FAC1_r	; string start pointer high byte
   228                          
   229                          sdescr		= FAC_sc	; string descriptor pointer
   230                          
   231                          csidx			= $BA		; line crunch save index
   232                          Asptl			= csidx	; array size/pointer low byte
   233                          Aspth			= $BB		; array size/pointer high byte
   234                          
   235                          Btmpl			= Asptl	; BASIC pointer temp low byte
   236                          Btmph			= Aspth	; BASIC pointer temp low byte
   237                          
   238                          Cptrl			= Asptl	; BASIC pointer temp low byte
   239                          Cptrh			= Aspth	; BASIC pointer temp low byte
   240                          
   241                          Sendl			= Asptl	; BASIC pointer temp low byte
   242                          Sendh			= Aspth	; BASIC pointer temp low byte
   243                          
   244                          LAB_IGBY		= $BC		; get next BASIC byte subroutine
   245                          
   246                          LAB_GBYT		= $C2		; get current BASIC byte subroutine
   247                          Bpntrl		= $C3		; BASIC execute (get byte) pointer low byte
   248                          Bpntrh		= Bpntrl+1	; BASIC execute (get byte) pointer high byte
   249                          
   250                          ;			= $D7		; end of get BASIC char subroutine
   251                          
   252                          Rbyte4		= $D8		; extra PRNG byte
   253                          Rbyte1		= Rbyte4+1	; most significant PRNG byte
   254                          Rbyte2		= Rbyte4+2	; middle PRNG byte
   255                          Rbyte3		= Rbyte4+3	; least significant PRNG byte
   256                          
   257                          NmiBase		= $DC		; NMI handler enabled/setup/triggered flags
   258                          					; bit	function
   259                          					; ===	========
   260                          					; 7	interrupt enabled
   261                          					; 6	interrupt setup
   262                          					; 5	interrupt happened
   263                          ;			= $DD		; NMI handler addr low byte
   264                          ;			= $DE		; NMI handler addr high byte
   265                          IrqBase		= $DF		; IRQ handler enabled/setup/triggered flags
   266                          ;			= $E0		; IRQ handler addr low byte
   267                          ;			= $E1		; IRQ handler addr high byte
   268                          
   269                          ;			= $DE		; unused
   270                          ;			= $DF		; unused
   271                          ;			= $E0		; unused
   272                          ;			= $E1		; unused
   273                          ;			= $E2		; unused
   274                          ;			= $E3		; unused
   275                          ;			= $E4		; unused
   276                          ;			= $E5		; unused
   277                          ;			= $E6		; unused
   278                          ;			= $E7		; unused
   279                          ;			= $E8		; unused
   280                          ;			= $E9		; unused
   281                          ;			= $EA		; unused
   282                          ;			= $EB		; unused
   283                          ;			= $EC		; unused
   284                          ;			= $ED		; unused
   285                          ;			= $EE		; unused
   286                          
   287                          Decss			= $E2		; number to decimal string start
   288                          Decssp1		= Decss+1	; number to decimal string start
   289                          
   290                          ;			= $FF		; decimal string end
   291                          
   292                          ; token values needed for BASIC
   293                          
   294                          ; primary command tokens (can start a statement)
   295                          
   296                          TK_END		= $80			; END token
   297                          TK_FOR		= TK_END+1		; FOR token
   298                          TK_NEXT		= TK_FOR+1		; NEXT token
   299                          TK_DATA		= TK_NEXT+1		; DATA token
   300                          TK_INPUT		= TK_DATA+1		; INPUT token
   301                          TK_DIM		= TK_INPUT+1	; DIM token
   302                          TK_READ		= TK_DIM+1		; READ token
   303                          TK_LET		= TK_READ+1		; LET token
   304                          TK_DEC		= TK_LET+1		; DEC token
   305                          TK_GOTO		= TK_DEC+1		; GOTO token
   306                          TK_RUN		= TK_GOTO+1		; RUN token
   307                          TK_IF			= TK_RUN+1		; IF token
   308                          TK_RESTORE		= TK_IF+1		; RESTORE token
   309                          TK_GOSUB		= TK_RESTORE+1	; GOSUB token
   310                          TK_RETIRQ		= TK_GOSUB+1	; RETIRQ token
   311                          TK_RETNMI		= TK_RETIRQ+1	; RETNMI token
   312                          TK_RETURN		= TK_RETNMI+1	; RETURN token
   313                          TK_REM		= TK_RETURN+1	; REM token
   314                          TK_STOP		= TK_REM+1		; STOP token
   315                          TK_ON			= TK_STOP+1		; ON token
   316                          TK_NULL		= TK_ON+1		; NULL token
   317                          TK_INC		= TK_NULL+1		; INC token
   318                          TK_WAIT		= TK_INC+1		; WAIT token
   319                          TK_LOAD		= TK_WAIT+1		; LOAD token
   320                          TK_SAVE		= TK_LOAD+1		; SAVE token
   321                          TK_DEF		= TK_SAVE+1		; DEF token
   322                          TK_POKE		= TK_DEF+1		; POKE token
   323                          TK_DOKE		= TK_POKE+1		; DOKE token
   324                          TK_DISPLAY	= TK_DOKE+1		; DISPLAY token
   325                          TK_PLOT		= TK_DISPLAY+1		; PLOT token
   326                          TK_CALL		= TK_PLOT+1		; CALL token
   327                          TK_DO			= TK_CALL+1		; DO token
   328                          TK_LOOP		= TK_DO+1		; LOOP token
   329                          TK_PRINT		= TK_LOOP+1		; PRINT token
   330                          TK_CONT		= TK_PRINT+1	; CONT token
   331                          TK_LIST		= TK_CONT+1		; LIST token
   332                          TK_CLEAR		= TK_LIST+1		; CLEAR token
   333                          TK_NEW		= TK_CLEAR+1	; NEW token
   334                          TK_WIDTH		= TK_NEW+1		; WIDTH token
   335                          TK_GET		= TK_WIDTH+1	; GET token
   336                          TK_SWAP		= TK_GET+1		; SWAP token
   337                          TK_BITSET		= TK_SWAP+1		; BITSET token
   338                          TK_BITCLR		= TK_BITSET+1	; BITCLR token
   339                          TK_IRQ		= TK_BITCLR+1	; IRQ token
   340                          TK_NMI		= TK_IRQ+1		; NMI token
   341                          
   342                          ; secondary command tokens, can't start a statement
   343                          
   344                          TK_TAB		= TK_NMI+1		; TAB token
   345                          TK_ELSE		= TK_TAB+1		; ELSE token
   346                          TK_TO			= TK_ELSE+1		; TO token
   347                          TK_FN			= TK_TO+1		; FN token
   348                          TK_SPC		= TK_FN+1		; SPC token
   349                          TK_THEN		= TK_SPC+1		; THEN token
   350                          TK_NOT		= TK_THEN+1		; NOT token
   351                          TK_STEP		= TK_NOT+1		; STEP token
   352                          TK_UNTIL		= TK_STEP+1		; UNTIL token
   353                          TK_WHILE		= TK_UNTIL+1	; WHILE token
   354                          TK_OFF		= TK_WHILE+1	; OFF token
   355                          
   356                          ; opperator tokens
   357                          
   358                          TK_PLUS		= TK_OFF+1		; + token
   359                          TK_MINUS		= TK_PLUS+1		; - token
   360                          TK_MUL		= TK_MINUS+1	; * token
   361                          TK_DIV		= TK_MUL+1		; / token
   362                          TK_POWER		= TK_DIV+1		; ^ token
   363                          TK_AND		= TK_POWER+1	; AND token
   364                          TK_EOR		= TK_AND+1		; EOR token
   365                          TK_OR			= TK_EOR+1		; OR token
   366                          TK_RSHIFT		= TK_OR+1		; RSHIFT token
   367                          TK_LSHIFT		= TK_RSHIFT+1	; LSHIFT token
   368                          TK_GT			= TK_LSHIFT+1	; > token
   369                          TK_EQUAL		= TK_GT+1		; = token
   370                          TK_LT			= TK_EQUAL+1	; < token
   371                          
   372                          ; functions tokens
   373                          
   374                          TK_SGN		= TK_LT+1		; SGN token
   375                          TK_INT		= TK_SGN+1		; INT token
   376                          TK_ABS		= TK_INT+1		; ABS token
   377                          TK_USR		= TK_ABS+1		; USR token
   378                          TK_FRE		= TK_USR+1		; FRE token
   379                          TK_POS		= TK_FRE+1		; POS token
   380                          TK_SQR		= TK_POS+1		; SQR token
   381                          TK_RND		= TK_SQR+1		; RND token
   382                          TK_LOG		= TK_RND+1		; LOG token
   383                          TK_EXP		= TK_LOG+1		; EXP token
   384                          TK_COS		= TK_EXP+1		; COS token
   385                          TK_SIN		= TK_COS+1		; SIN token
   386                          TK_TAN		= TK_SIN+1		; TAN token
   387                          TK_ATN		= TK_TAN+1		; ATN token
   388                          TK_PEEK		= TK_ATN+1		; PEEK token
   389                          TK_DEEK		= TK_PEEK+1		; DEEK token
   390                          TK_SADD		= TK_DEEK+1		; SADD token
   391                          TK_LEN		= TK_SADD+1		; LEN token
   392                          TK_STRS		= TK_LEN+1		; STR$ token
   393                          TK_VAL		= TK_STRS+1		; VAL token
   394                          TK_ASC		= TK_VAL+1		; ASC token
   395                          TK_UCASES		= TK_ASC+1		; UCASE$ token
   396                          TK_LCASES		= TK_UCASES+1	; LCASE$ token
   397                          TK_CHRS		= TK_LCASES+1	; CHR$ token
   398                          TK_HEXS		= TK_CHRS+1		; HEX$ token
   399                          TK_BINS		= TK_HEXS+1		; BIN$ token
   400                          TK_BITTST		= TK_BINS+1		; BITTST token
   401                          TK_MAX		= TK_BITTST+1	; MAX token
   402                          TK_MIN		= TK_MAX+1		; MIN token
   403                          TK_PI			= TK_MIN+1		; PI token
   404                          TK_TWOPI		= TK_PI+1		; TWOPI token
   405                          TK_VPTR		= TK_TWOPI+1	; VARPTR token
   406                          TK_LEFTS		= TK_VPTR+1		; LEFT$ token
   407                          TK_RIGHTS		= TK_LEFTS+1	; RIGHT$ token
   408                          TK_MIDS		= TK_RIGHTS+1	; MID$ token
   409                          
   410                          ; offsets from a base of X or Y
   411                          
   412                          PLUS_0		= $00		; X or Y plus 0
   413                          PLUS_1		= $01		; X or Y plus 1
   414                          PLUS_2		= $02		; X or Y plus 2
   415                          PLUS_3		= $03		; X or Y plus 3
   416                          
   417                          LAB_STAK		= $0100	; stack bottom, no offset
   418                          
   419                          LAB_SKFE		= LAB_STAK+$FE
   420                          					; flushed stack address
   421                          LAB_SKFF		= LAB_STAK+$FF
   422                          					; flushed stack address
   423                          
   424                          ccflag		= $0300	; BASIC CTRL-C flag, 00 = enabled, 01 = dis
   425                          ccbyte		= ccflag+1	; BASIC CTRL-C byte
   426                          ccnull		= ccbyte+1	; BASIC CTRL-C byte timeout
   427                          
   428                          VEC_CC		= ccnull+1	; ctrl c check vector
   429                          
   430                          VEC_IN		= VEC_CC+2	; input vector
   431                          VEC_OUT		= VEC_IN+2	; output vector
   432                          VEC_LD		= VEC_OUT+2	; load vector
   433                          VEC_SV		= VEC_LD+2	; save vector
   434                          
   435                          ; Ibuffs can now be anywhere in RAM, ensure that the max length is < $80
   436                          
   437                          Ibuffs		= IRQ_vec+$14
   438                          					; start of input buffer after IRQ/NMI code
   439                          Ibuffe		= Ibuffs+$47; end of input buffer
   440                          
   441                          Ram_base	= $0400	; start of user RAM (set as needed, should be page aligned)
   442                          Ram_top		= $7000	; end of user RAM+1 (set as needed, should be page aligned)
   443                          
   444                          ; This start can be changed to suit your system
   445                          
   446                          *=$9000
   447                          
   448                          ; For convenience, put jump here to reset location so it can be
   449                          ; run from the load address.
   450                          
   451  9000 4c7bb8             JMP	RES_vec
   452                          
   453                          ; BASIC cold start entry point
   454                          
   455                          ; new page 2 initialisation, copy block to ccflag on
   456                          
   457                          LAB_COLD
   458  9003 a004               	LDY	#PG2_TABE-PG2_TABS-1
   459                          					; byte count-1
   460                          LAB_2D13
   461  9005 b922b1             	LDA	PG2_TABS,Y		; get byte
   462  9008 990003             	STA	ccflag,Y		; store in page 2
   463  900b 88                 	DEY				; decrement count
   464  900c 10f7               	BPL	LAB_2D13		; loop if not done
   465                          
   466  900e a2ff               	LDX	#$FF			; set byte
   467  9010 8688               	STX	Clineh		; set current line high byte (set immediate mode)
   468  9012 9a                 	TXS				; reset stack pointer
   469                          
   470  9013 a94c               	LDA	#$4C			; code for JMP
   471  9015 85a1               	STA	Fnxjmp		; save for jump vector for functions
   472                          
   473                          ; copy block from LAB_2CEE to $00BC - $00D3
   474                          
   475  9017 a21c               	LDX	#StrTab-LAB_2CEE	; set byte count
   476                          LAB_2D4E
   477  9019 bd26b1             	LDA	LAB_2CEE-1,X	; get byte from table
   478  901c 95bb               	STA	LAB_IGBY-1,X	; save byte in page zero
   479  901e ca                 	DEX				; decrement count
   480  901f d0f8               	BNE	LAB_2D4E		; loop if not all done
   481                          
   482                          ; copy block from StrTab to $0000 - $0012
   483                          
   484                          LAB_GMEM
   485  9021 a212               	LDX	#EndTab-StrTab-1	; set byte count-1
   486                          TabLoop
   487  9023 bd43b1             	LDA	StrTab,X		; get byte from table
   488  9026 9500               	STA	PLUS_0,X		; save byte in page zero
   489  9028 ca                 	DEX				; decrement count
   490  9029 10f8               	BPL	TabLoop		; loop if not all done
   491                          
   492                          ; set-up start values
   493                          
   494  902b a900               	LDA	#$00			; clear A
   495  902d 85dc               	STA	NmiBase		; clear NMI handler enabled flag
   496  902f 85df               	STA	IrqBase		; clear IRQ handler enabled flag
   497  9031 85b2               	STA	FAC1_o		; clear FAC1 overflow byte
   498  9033 8567               	STA	last_sh		; clear descriptor stack top item pointer high byte
   499                          
   500  9035 a90e               	LDA	#$0E			; set default tab size
   501  9037 8564               	STA	TabSiz		; save it
   502  9039 a903               	LDA	#$03			; set garbage collect step size for descriptor stack
   503  903b 85a0               	STA	g_step		; save it
   504  903d a268               	LDX	#des_sk		; descriptor stack start
   505  903f 8665               	STX	next_s		; set descriptor stack pointer
   506                          
   507  9041 a900               	lda #$00
   508  9043 8511               	sta Itempl
   509  9045 a968               	lda #$68
   510  9047 8512               	sta Itemph	; 16KB
   511                          
   512  9049 4c6490                     JMP LAB_2D93    ; Skip memory question
   513                          
   514  904c 20ae98             	JSR	LAB_CRLF		; print CR/LF
   515  904f a956               	LDA	#<LAB_MSZM		; point to memory size message (low addr)
   516  9051 a0b1               	LDY	#>LAB_MSZM		; point to memory size message (high addr)
   517  9053 20ea98             	JSR	LAB_18C3		; print null terminated string from memory
   518  9056 204b92             	JSR	LAB_INLN		; print "? " and get BASIC input
   519  9059 86c3               	STX	Bpntrl		; set BASIC execute pointer low byte
   520  905b 84c4               	STY	Bpntrh		; set BASIC execute pointer high byte
   521  905d 20c200             	JSR	LAB_GBYT		; get last byte back
   522                          
   523  9060 d01f               	BNE	LAB_2DAA		; branch if not null (user typed something)
   524                          
   525  9062 a000               	LDY	#$00			; else clear Y
   526                          					; character was null so get memory size the hard way
   527                          					; we get here with Y=0 and Itempl/h = Ram_base
   528                          LAB_2D93
   529  9064 e611               	INC	Itempl		; increment temporary integer low byte
   530  9066 d008               	BNE	LAB_2D99		; branch if no overflow
   531                          
   532  9068 e612               	INC	Itemph		; increment temporary integer high byte
   533  906a a512               	LDA	Itemph		; get high byte
   534  906c c970               	CMP	#>Ram_top		; compare with top of RAM+1
   535  906e f01d               	BEQ	LAB_2DB6		; branch if match (end of user RAM)
   536                          
   537                          LAB_2D99
   538  9070 a955               	LDA	#$55			; set test byte
   539  9072 9111               	STA	(Itempl),Y		; save via temporary integer
   540  9074 d111               	CMP	(Itempl),Y		; compare via temporary integer
   541  9076 d015               	BNE	LAB_2DB6		; branch if fail
   542                          
   543  9078 0a                 	ASL				; shift test byte left (now $AA)
   544  9079 9111               	STA	(Itempl),Y		; save via temporary integer
   545  907b d111               	CMP	(Itempl),Y		; compare via temporary integer
   546  907d f0e5               	BEQ	LAB_2D93		; if ok go do next byte
   547                          
   548  907f d00c               	BNE	LAB_2DB6		; branch if fail
   549                          
   550                          LAB_2DAA
   551  9081 20bda9             	JSR	LAB_2887		; get FAC1 from string
   552  9084 a5ac               	LDA	FAC1_e		; get FAC1 exponent
   553  9086 c998               	CMP	#$98			; compare with exponent = 2^24
   554  9088 b097               	BCS	LAB_GMEM		; if too large go try again
   555                          
   556  908a 200ea5             	JSR	LAB_F2FU		; save integer part of FAC1 in temporary integer
   557                          					; (no range check)
   558                          
   559                          LAB_2DB6
   560  908d a511               	LDA	Itempl		; get temporary integer low byte
   561  908f a412               	LDY	Itemph		; get temporary integer high byte
   562  9091 c001               	CPY	#<Ram_base+1	; compare with start of RAM+$100 high byte
   563  9093 908c               	BCC	LAB_GMEM		; if too small go try again
   564                          
   565                          
   566                          ; uncomment these lines if you want to check on the high limit of memory. Note if
   567                          ; Ram_top is set too low then this will fail. default is ignore it and assume the
   568                          ; users know what they're doing!
   569                          
   570                          ;	CPY	#>Ram_top		; compare with top of RAM high byte
   571                          ;	BCC	MEM_OK		; branch if < RAM top
   572                          
   573                          ;	BNE	LAB_GMEM		; if too large go try again
   574                          					; else was = so compare low bytes
   575                          ;	CMP	#<Ram_top		; compare with top of RAM low byte
   576                          ;	BEQ	MEM_OK		; branch if = RAM top
   577                          
   578                          ;	BCS	LAB_GMEM		; if too large go try again
   579                          
   580                          ;MEM_OK
   581  9095 8585               	STA	Ememl			; set end of mem low byte
   582  9097 8486               	STY	Ememh			; set end of mem high byte
   583  9099 8581               	STA	Sstorl		; set bottom of string space low byte
   584  909b 8482               	STY	Sstorh		; set bottom of string space high byte
   585                          
   586  909d a000               	LDY	#<Ram_base		; set start addr low byte
   587  909f a204               	LDX	#>Ram_base		; set start addr high byte
   588  90a1 8479               	STY	Smeml			; save start of mem low byte
   589  90a3 867a               	STX	Smemh			; save start of mem high byte
   590                          
   591                          ; this line is only needed if Ram_base is not $xx00
   592                          
   593                          ;	LDY	#$00			; clear Y
   594  90a5 98                 	TYA				; clear A
   595  90a6 9179               	STA	(Smeml),Y		; clear first byte
   596  90a8 e679               	INC	Smeml			; increment start of mem low byte
   597                          
   598                          ; these two lines are only needed if Ram_base is $xxFF
   599                          
   600                          ;	BNE	LAB_2E05		; branch if no rollover
   601                          
   602                          ;	INC	Smemh			; increment start of mem high byte
   603                          LAB_2E05
   604                          	;JSR	LAB_CRLF		; print CR/LF
   605  90aa 206793             	JSR	LAB_1463		; do "NEW" and "CLEAR"
   606  90ad a585               	LDA	Ememl			; get end of mem low byte
   607  90af 38                 	SEC				; set carry for subtract
   608  90b0 e579               	SBC	Smeml			; subtract start of mem low byte
   609  90b2 aa                 	TAX				; copy to X
   610  90b3 a586               	LDA	Ememh			; get end of mem high byte
   611  90b5 e57a               	SBC	Smemh			; subtract start of mem high byte
   612                          
   613                          ; TS: Don't print free RAM
   614                          ;	JSR	LAB_295E		; print XA as unsigned integer (bytes free)
   615                          
   616  90b7 20ae98             	JSR	LAB_CRLF		; print CR/LF
   617  90ba a965               	LDA	#<LAB_SMSG		; point to sign-on message (low addr)
   618  90bc a0b1               	LDY	#>LAB_SMSG		; point to sign-on message (high addr)
   619  90be 20ea98             	JSR	LAB_18C3		; print null terminated string from memory
   620  90c1 a965               	LDA	#<LAB_1274		; warm start vector low byte
   621  90c3 a091               	LDY	#>LAB_1274		; warm start vector high byte
   622  90c5 8501               	STA	Wrmjpl		; save warm start vector low byte
   623  90c7 8402               	STY	Wrmjph		; save warm start vector high byte
   624  90c9 6c0100             	JMP	(Wrmjpl)		; go do warm start
   625                          
   626                          ; open up space in memory
   627                          ; move (Ostrtl)-(Obendl) to new block ending at (Nbendl)
   628                          
   629                          ; Nbendl,Nbendh - new block end address (A/Y)
   630                          ; Obendl,Obendh - old block end address
   631                          ; Ostrtl,Ostrth - old block start address
   632                          
   633                          ; returns with ..
   634                          
   635                          ; Nbendl,Nbendh - new block start address (high byte - $100)
   636                          ; Obendl,Obendh - old block start address (high byte - $100)
   637                          ; Ostrtl,Ostrth - old block start address (unchanged)
   638                          
   639                          LAB_11CF
   640  90cc 201691             	JSR	LAB_121F		; check available memory, "Out of memory" error if no room
   641                          					; addr to check is in AY (low/high)
   642  90cf 857f               	STA	Earryl		; save new array mem end low byte
   643  90d1 8480               	STY	Earryh		; save new array mem end high byte
   644                          
   645                          ; open up space in memory
   646                          ; move (Ostrtl)-(Obendl) to new block ending at (Nbendl)
   647                          ; don't set array end
   648                          
   649                          LAB_11D6
   650  90d3 38                 	SEC				; set carry for subtract
   651  90d4 a5a6               	LDA	Obendl		; get block end low byte
   652  90d6 e5aa               	SBC	Ostrtl		; subtract block start low byte
   653  90d8 a8                 	TAY				; copy MOD(block length/$100) byte to Y
   654  90d9 a5a7               	LDA	Obendh		; get block end high byte
   655  90db e5ab               	SBC	Ostrth		; subtract block start high byte
   656  90dd aa                 	TAX				; copy block length high byte to X
   657  90de e8                 	INX				; +1 to allow for count=0 exit
   658  90df 98                 	TYA				; copy block length low byte to A
   659  90e0 f024               	BEQ	LAB_120A		; branch if length low byte=0
   660                          
   661                          					; block is (X-1)*256+Y bytes, do the Y bytes first
   662                          
   663  90e2 38                 	SEC				; set carry for add + 1, two's complement
   664  90e3 49ff               	EOR	#$FF			; invert low byte for subtract
   665  90e5 65a6               	ADC	Obendl		; add block end low byte
   666                          
   667  90e7 85a6               	STA	Obendl		; save corrected old block end low byte
   668  90e9 b003               	BCS	LAB_11F3		; branch if no underflow
   669                          
   670  90eb c6a7               	DEC	Obendh		; else decrement block end high byte
   671  90ed 38                 	SEC				; set carry for add + 1, two's complement
   672                          LAB_11F3
   673  90ee 98                 	TYA				; get MOD(block length/$100) byte
   674  90ef 49ff               	EOR	#$FF			; invert low byte for subtract
   675  90f1 65a4               	ADC	Nbendl		; add destination end low byte
   676  90f3 85a4               	STA	Nbendl		; save modified new block end low byte
   677  90f5 b008               	BCS	LAB_1203		; branch if no underflow
   678                          
   679  90f7 c6a5               	DEC	Nbendh		; else decrement block end high byte
   680  90f9 9004               	BCC	LAB_1203		; branch always
   681                          
   682                          LAB_11FF
   683  90fb b1a6               	LDA	(Obendl),Y		; get byte from source
   684  90fd 91a4               	STA	(Nbendl),Y		; copy byte to destination
   685                          LAB_1203
   686  90ff 88                 	DEY				; decrement index
   687  9100 d0f9               	BNE	LAB_11FF		; loop until Y=0
   688                          
   689                          					; now do Y=0 indexed byte
   690  9102 b1a6               	LDA	(Obendl),Y		; get byte from source
   691  9104 91a4               	STA	(Nbendl),Y		; save byte to destination
   692                          LAB_120A
   693  9106 c6a7               	DEC	Obendh		; decrement source pointer high byte
   694  9108 c6a5               	DEC	Nbendh		; decrement destination pointer high byte
   695  910a ca                 	DEX				; decrement block count
   696  910b d0f2               	BNE	LAB_1203		; loop until count = $0
   697                          
   698  910d 60                 	RTS
   699                          
   700                          ; check room on stack for A bytes
   701                          ; stack too deep? do OM error
   702                          
   703                          LAB_1212
   704  910e 8578               	STA	TempB			; save result in temp byte
   705  9110 ba                 	TSX				; copy stack
   706  9111 e478               	CPX	TempB			; compare new "limit" with stack
   707  9113 9030               	BCC	LAB_OMER		; if stack < limit do "Out of memory" error then warm start
   708                          
   709  9115 60                 	RTS
   710                          
   711                          ; check available memory, "Out of memory" error if no room
   712                          ; addr to check is in AY (low/high)
   713                          
   714                          LAB_121F
   715  9116 c482               	CPY	Sstorh		; compare bottom of string mem high byte
   716  9118 902a               	BCC	LAB_124B		; if less then exit (is ok)
   717                          
   718  911a d004               	BNE	LAB_1229		; skip next test if greater (tested <)
   719                          
   720                          					; high byte was =, now do low byte
   721  911c c581               	CMP	Sstorl		; compare with bottom of string mem low byte
   722  911e 9024               	BCC	LAB_124B		; if less then exit (is ok)
   723                          
   724                          					; addr is > string storage ptr (oops!)
   725                          LAB_1229
   726  9120 48                 	PHA				; push addr low byte
   727  9121 a208               	LDX	#$08			; set index to save Adatal to expneg inclusive
   728  9123 98                 	TYA				; copy addr high byte (to push on stack)
   729                          
   730                          					; save misc numeric work area
   731                          LAB_122D
   732  9124 48                 	PHA				; push byte
   733  9125 b5a3               	LDA	Adatal-1,X		; get byte from Adatal to expneg ( ,$00 not pushed)
   734  9127 ca                 	DEX				; decrement index
   735  9128 10fa               	BPL	LAB_122D		; loop until all done
   736                          
   737  912a 20f6a1             	JSR	LAB_GARB		; garbage collection routine
   738                          
   739                          					; restore misc numeric work area
   740  912d a200               	LDX	#$00			; clear the index to restore bytes
   741                          LAB_1238
   742  912f 68                 	PLA				; pop byte
   743  9130 95a4               	STA	Adatal,X		; save byte to Adatal to expneg
   744  9132 e8                 	INX				; increment index
   745  9133 e008               	CPX	#$08			; compare with end + 1
   746  9135 30f8               	BMI	LAB_1238		; loop if more to do
   747                          
   748  9137 68                 	PLA				; pop addr high byte
   749  9138 a8                 	TAY				; copy back to Y
   750  9139 68                 	PLA				; pop addr low byte
   751  913a c482               	CPY	Sstorh		; compare bottom of string mem high byte
   752  913c 9006               	BCC	LAB_124B		; if less then exit (is ok)
   753                          
   754  913e d005               	BNE	LAB_OMER		; if greater do "Out of memory" error then warm start
   755                          
   756                          					; high byte was =, now do low byte
   757  9140 c581               	CMP	Sstorl		; compare with bottom of string mem low byte
   758  9142 b001               	BCS	LAB_OMER		; if >= do "Out of memory" error then warm start
   759                          
   760                          					; ok exit, carry clear
   761                          LAB_124B
   762  9144 60                 	RTS
   763                          
   764                          ; do "Out of memory" error then warm start
   765                          
   766                          LAB_OMER
   767  9145 a20c               	LDX	#$0C			; error code $0C ("Out of memory" error)
   768                          
   769                          ; do error #X, then warm start
   770                          
   771                          LAB_XERR
   772  9147 20ae98             	JSR	LAB_CRLF		; print CR/LF
   773                          
   774  914a bdecb6             	LDA	LAB_BAER,X		; get error message pointer low byte
   775  914d bcedb6             	LDY	LAB_BAER+1,X	; get error message pointer high byte
   776  9150 20ea98             	JSR	LAB_18C3		; print null terminated string from memory
   777                          
   778  9153 20a093             	JSR	LAB_1491		; flush stack and clear continue flag
   779  9156 a93a               	LDA	#<LAB_EMSG		; point to " Error" low addr
   780  9158 a0b8               	LDY	#>LAB_EMSG		; point to " Error" high addr
   781                          LAB_1269
   782  915a 20ea98             	JSR	LAB_18C3		; print null terminated string from memory
   783  915d a488               	LDY	Clineh		; get current line high byte
   784  915f c8                 	INY				; increment it
   785  9160 f003               	BEQ	LAB_1274		; go do warm start (was immediate mode)
   786                          
   787                          					; else print line number
   788  9162 208eaa             	JSR	LAB_2953		; print " in line [LINE #]"
   789                          
   790                          ; BASIC warm start entry point
   791                          ; wait for Basic command
   792                          
   793                          LAB_1274
   794                          				; clear ON IRQ/NMI bytes
   795  9165 a900               	LDA	#$00		; clear A
   796  9167 85df               	STA	IrqBase		; clear enabled byte
   797  9169 85dc               	STA	NmiBase		; clear enabled byte
   798  916b a94c               	LDA	#<LAB_RMSG		; point to "Ready" message low byte
   799  916d a0b8               	LDY	#>LAB_RMSG		; point to "Ready" message high byte
   800                          
   801  916f 20ea98             	JSR	LAB_18C3		; go do print string
   802                          
   803                          ; wait for Basic command (no "Ready")
   804                          
   805                          LAB_127D
   806  9172 205892             	JSR	LAB_1357		; call for BASIC input
   807                          LAB_1280
   808  9175 86c3               	STX	Bpntrl		; set BASIC execute pointer low byte
   809  9177 84c4               	STY	Bpntrh		; set BASIC execute pointer high byte
   810  9179 20c200             	JSR	LAB_GBYT		; scan memory
   811  917c f0f4               	BEQ	LAB_127D		; loop while null
   812                          
   813                          ; got to interpret input line now ..
   814                          
   815  917e a2ff               	LDX	#$FF			; current line to null value
   816  9180 8688               	STX	Clineh		; set current line high byte
   817  9182 9006               	BCC	LAB_1295		; branch if numeric character (handle new BASIC line)
   818                          
   819                          					; no line number .. immediate mode
   820  9184 208992             	JSR	LAB_13A6		; crunch keywords into Basic tokens
   821  9187 4c0a95             	JMP	LAB_15F6		; go scan and interpret code
   822                          
   823                          ; handle new BASIC line
   824                          
   825                          LAB_1295
   826  918a 207197             	JSR	LAB_GFPN		; get fixed-point number into temp integer
   827  918d 208992             	JSR	LAB_13A6		; crunch keywords into Basic tokens
   828  9190 845d               	STY	Ibptr			; save index pointer to end of crunched line
   829  9192 203b93             	JSR	LAB_SSLN		; search BASIC for temp integer line number
   830  9195 9044               	BCC	LAB_12E6		; branch if not found
   831                          
   832                          					; aroooogah! line # already exists! delete it
   833  9197 a001               	LDY	#$01			; set index to next line pointer high byte
   834  9199 b1aa               	LDA	(Baslnl),Y		; get next line pointer high byte
   835  919b 8572               	STA	ut1_ph		; save it
   836  919d a57b               	LDA	Svarl			; get start of vars low byte
   837  919f 8571               	STA	ut1_pl		; save it
   838  91a1 a5ab               	LDA	Baslnh		; get found line pointer high byte
   839  91a3 8574               	STA	ut2_ph		; save it
   840  91a5 a5aa               	LDA	Baslnl		; get found line pointer low byte
   841  91a7 88                 	DEY				; decrement index
   842  91a8 f1aa               	SBC	(Baslnl),Y		; subtract next line pointer low byte
   843  91aa 18                 	CLC				; clear carry for add
   844  91ab 657b               	ADC	Svarl			; add start of vars low byte
   845  91ad 857b               	STA	Svarl			; save new start of vars low byte
   846  91af 8573               	STA	ut2_pl		; save destination pointer low byte
   847  91b1 a57c               	LDA	Svarh			; get start of vars high byte
   848  91b3 69ff               	ADC	#$FF			; -1 + carry
   849  91b5 857c               	STA	Svarh			; save start of vars high byte
   850  91b7 e5ab               	SBC	Baslnh		; subtract found line pointer high byte
   851  91b9 aa                 	TAX				; copy to block count
   852  91ba 38                 	SEC				; set carry for subtract
   853  91bb a5aa               	LDA	Baslnl		; get found line pointer low byte
   854  91bd e57b               	SBC	Svarl			; subtract start of vars low byte
   855  91bf a8                 	TAY				; copy to bytes in first block count
   856  91c0 b003               	BCS	LAB_12D0		; branch if overflow
   857                          
   858  91c2 e8                 	INX				; increment block count (correct for =0 loop exit)
   859  91c3 c674               	DEC	ut2_ph		; decrement destination high byte
   860                          LAB_12D0
   861  91c5 18                 	CLC				; clear carry for add
   862  91c6 6571               	ADC	ut1_pl		; add source pointer low byte
   863  91c8 9003               	BCC	LAB_12D8		; branch if no overflow
   864                          
   865  91ca c672               	DEC	ut1_ph		; else decrement source pointer high byte
   866  91cc 18                 	CLC				; clear carry
   867                          
   868                          					; close up memory to delete old line
   869                          LAB_12D8
   870  91cd b171               	LDA	(ut1_pl),Y		; get byte from source
   871  91cf 9173               	STA	(ut2_pl),Y		; copy to destination
   872  91d1 c8                 	INY				; increment index
   873  91d2 d0f9               	BNE	LAB_12D8		; while <> 0 do this block
   874                          
   875  91d4 e672               	INC	ut1_ph		; increment source pointer high byte
   876  91d6 e674               	INC	ut2_ph		; increment destination pointer high byte
   877  91d8 ca                 	DEX				; decrement block count
   878  91d9 d0f2               	BNE	LAB_12D8		; loop until all done
   879                          
   880                          					; got new line in buffer and no existing same #
   881                          LAB_12E6
   882  91db ad2103             	LDA	Ibuffs		; get byte from start of input buffer
   883  91de f03f               	BEQ	LAB_1319		; if null line just go flush stack/vars and exit
   884                          
   885                          					; got new line and it isn't empty line
   886  91e0 a585               	LDA	Ememl			; get end of mem low byte
   887  91e2 a486               	LDY	Ememh			; get end of mem high byte
   888  91e4 8581               	STA	Sstorl		; set bottom of string space low byte
   889  91e6 8482               	STY	Sstorh		; set bottom of string space high byte
   890  91e8 a57b               	LDA	Svarl			; get start of vars low byte	(end of BASIC)
   891  91ea 85a6               	STA	Obendl		; save old block end low byte
   892  91ec a47c               	LDY	Svarh			; get start of vars high byte	(end of BASIC)
   893  91ee 84a7               	STY	Obendh		; save old block end high byte
   894  91f0 655d               	ADC	Ibptr			; add input buffer pointer	(also buffer length)
   895  91f2 9001               	BCC	LAB_1301		; branch if no overflow from add
   896                          
   897  91f4 c8                 	INY				; else increment high byte
   898                          LAB_1301
   899  91f5 85a4               	STA	Nbendl		; save new block end low byte	(move to, low byte)
   900  91f7 84a5               	STY	Nbendh		; save new block end high byte
   901  91f9 20cc90             	JSR	LAB_11CF		; open up space in memory
   902                          					; old start pointer Ostrtl,Ostrth set by the find line call
   903  91fc a57f               	LDA	Earryl		; get array mem end low byte
   904  91fe a480               	LDY	Earryh		; get array mem end high byte
   905  9200 857b               	STA	Svarl			; save start of vars low byte
   906  9202 847c               	STY	Svarh			; save start of vars high byte
   907  9204 a45d               	LDY	Ibptr			; get input buffer pointer	(also buffer length)
   908  9206 88                 	DEY				; adjust for loop type
   909                          LAB_1311
   910  9207 b91d03             	LDA	Ibuffs-4,Y		; get byte from crunched line
   911  920a 91aa               	STA	(Baslnl),Y		; save it to program memory
   912  920c 88                 	DEY				; decrement count
   913  920d c003               	CPY	#$03			; compare with first byte-1
   914  920f d0f6               	BNE	LAB_1311		; continue while count <> 3
   915                          
   916  9211 a512               	LDA	Itemph		; get line # high byte
   917  9213 91aa               	STA	(Baslnl),Y		; save it to program memory
   918  9215 88                 	DEY				; decrement count
   919  9216 a511               	LDA	Itempl		; get line # low byte
   920  9218 91aa               	STA	(Baslnl),Y		; save it to program memory
   921  921a 88                 	DEY				; decrement count
   922  921b a9ff               	LDA	#$FF			; set byte to allow chain rebuild. if you didn't set this
   923                          					; byte then a zero already here would stop the chain rebuild
   924                          					; as it would think it was the [EOT] marker.
   925  921d 91aa               	STA	(Baslnl),Y		; save it to program memory
   926                          
   927                          LAB_1319
   928  921f 207c93             	JSR	LAB_1477		; reset execution to start, clear vars and flush stack
   929  9222 a679               	LDX	Smeml			; get start of mem low byte
   930  9224 a57a               	LDA	Smemh			; get start of mem high byte
   931  9226 a001               	LDY	#$01			; index to high byte of next line pointer
   932                          LAB_1325
   933  9228 8671               	STX	ut1_pl		; set line start pointer low byte
   934  922a 8572               	STA	ut1_ph		; set line start pointer high byte
   935  922c b171               	LDA	(ut1_pl),Y		; get it
   936  922e f018               	BEQ	LAB_133E		; exit if end of program
   937                          
   938                          ; rebuild chaining of Basic lines
   939                          
   940  9230 a004               	LDY	#$04			; point to first code byte of line
   941                          					; there is always 1 byte + [EOL] as null entries are deleted
   942                          LAB_1330
   943  9232 c8                 	INY				; next code byte
   944  9233 b171               	LDA	(ut1_pl),Y		; get byte
   945  9235 d0fb               	BNE	LAB_1330		; loop if not [EOL]
   946                          
   947  9237 38                 	SEC				; set carry for add + 1
   948  9238 98                 	TYA				; copy end index
   949  9239 6571               	ADC	ut1_pl		; add to line start pointer low byte
   950  923b aa                 	TAX				; copy to X
   951  923c a000               	LDY	#$00			; clear index, point to this line's next line pointer
   952  923e 9171               	STA	(ut1_pl),Y		; set next line pointer low byte
   953  9240 98                 	TYA				; clear A
   954  9241 6572               	ADC	ut1_ph		; add line start pointer high byte + carry
   955  9243 c8                 	INY				; increment index to high byte
   956  9244 9171               	STA	(ut1_pl),Y		; save next line pointer low byte
   957  9246 90e0               	BCC	LAB_1325		; go do next line, branch always, carry clear
   958                          
   959                          
   960                          LAB_133E
   961  9248 4c7291             	JMP	LAB_127D		; else we just wait for Basic command, no "Ready"
   962                          
   963                          ; print "? " and get BASIC input
   964                          
   965                          LAB_INLN
   966  924b 200299             	JSR	LAB_18E3		; print "?" character
   967  924e 20ff98             	JSR	LAB_18E0		; print " "
   968  9251 d005               	BNE	LAB_1357		; call for BASIC input and return
   969                          
   970                          ; receive line from keyboard
   971                          
   972                          					; $08 as delete key (BACKSPACE on standard keyboard)
   973                          LAB_134B
   974  9253 200499             	JSR	LAB_PRNA		; go print the character
   975  9256 ca                 	DEX				; decrement the buffer counter (delete)
   976  9257 2c                 	!text	$2C			; make LDX into BIT abs
   977                          
   978                          ; call for BASIC input (main entry point)
   979                          
   980                          LAB_1357
   981  9258 a200               	LDX	#$00			; clear BASIC line buffer pointer
   982                          LAB_1359
   983  925a 2016b1             	JSR	V_INPT		; call scan input device
   984  925d 90fb               	BCC	LAB_1359		; loop if no byte
   985                          
   986  925f f0f9               	BEQ	LAB_1359		; loop until valid input (ignore NULLs)
   987                          
   988  9261 c907               	CMP	#$07			; compare with [BELL]
   989  9263 f010               	BEQ	LAB_1378		; branch if [BELL]
   990                          
   991  9265 c90d               	CMP	#$0D			; compare with [CR]
   992  9267 f019               	BEQ	LAB_1384		; do CR/LF exit if [CR]
   993                          
   994  9269 e000               	CPX	#$00			; compare pointer with $00
   995  926b d004               	BNE	LAB_1374		; branch if not empty
   996                          
   997                          ; next two lines ignore any non print character and [SPACE] if input buffer empty
   998                          
   999  926d c921               	CMP	#$21			; compare with [SP]+1
  1000  926f 90e9               	BCC	LAB_1359		; if < ignore character
  1001                          
  1002                          LAB_1374
  1003  9271 c908               	CMP	#$08			; compare with [BACKSPACE] (delete last character)
  1004  9273 f0de               	BEQ	LAB_134B		; go delete last character
  1005                          
  1006                          LAB_1378
  1007  9275 e047               	CPX	#Ibuffe-Ibuffs	; compare character count with max
  1008  9277 b00c               	BCS	LAB_138E		; skip store and do [BELL] if buffer full
  1009                          
  1010  9279 9d2103             	STA	Ibuffs,X		; else store in buffer
  1011  927c e8                 	INX				; increment pointer
  1012                          LAB_137F
  1013  927d 200499             	JSR	LAB_PRNA		; go print the character
  1014  9280 d0d8               	BNE	LAB_1359		; always loop for next character
  1015                          
  1016                          LAB_1384
  1017  9282 4ca598             	JMP	LAB_1866		; do CR/LF exit to BASIC
  1018                          
  1019                          ; announce buffer full
  1020                          
  1021                          LAB_138E
  1022  9285 a907               	LDA	#$07			; [BELL] character into A
  1023  9287 d0f4               	BNE	LAB_137F		; go print the [BELL] but ignore input character
  1024                          					; branch always
  1025                          
  1026                          ; crunch keywords into Basic tokens
  1027                          ; position independent buffer version ..
  1028                          ; faster, dictionary search version ....
  1029                          
  1030                          LAB_13A6
  1031  9289 a0ff                     LDY   #$FF              ; set save index (makes for easy math later)
  1032                          
  1033  928b 38                       SEC                     ; set carry for subtract
  1034  928c a5c3                     LDA   Bpntrl            ; get basic execute pointer low byte
  1035  928e e921                     SBC   #<Ibuffs          ; subtract input buffer start pointer
  1036  9290 aa                       TAX                     ; copy result to X (index past line # if any)
  1037                          
  1038  9291 8660                     STX   Oquote            ; clear open quote/DATA flag
  1039                          LAB_13AC
  1040  9293 bd2103                   LDA   Ibuffs,X          ; get byte from input buffer
  1041  9296 f05d                     BEQ   LAB_13EC          ; if null save byte then exit
  1042                          
  1043                          ; Applied case sensitivity patch from 
  1044                          ; https://github.com/Klaus2m5/6502_EhBASIC_V2.22/blob/master/mixed_case_keywords_mod.txt
  1045                          ;
  1046                          ; *** begin patch: lower case token recognition V2 ***
  1047                          ; ***              WARNING! changes documented behavior!
  1048                          ; *** add
  1049  9298 c97b                     CMP   #'{'              ; convert lower to upper case
  1050  929a b059                     BCS   LAB_13EC          ; is above lower case
  1051  929c c961                     CMP   #'a'
  1052  929e 9002                     BCC   PATCH_LC          ; is below lower case
  1053  92a0 29df                     AND   #$DF              ; mask lower case bit
  1054                                
  1055                          PATCH_LC
  1056                          ; *** end
  1057                             
  1058  92a2 c95f                     CMP   #'_'              ; compare with "_"
  1059  92a4 b04f                     BCS   LAB_13EC          ; if >= go save byte then continue crunching
  1060                          
  1061  92a6 c93c                     CMP   #'<'              ; compare with "<"
  1062  92a8 b00e                     BCS   LAB_13CC          ; if >= go crunch now
  1063                          
  1064  92aa c930                     CMP   #'0'              ; compare with "0"
  1065  92ac b047                     BCS   LAB_13EC          ; if >= go save byte then continue crunching
  1066                          
  1067  92ae 855c                     STA   Scnquo            ; save buffer byte as search character
  1068  92b0 c922                     CMP   #$22              ; is it quote character?
  1069  92b2 f063                     BEQ   LAB_1410          ; branch if so (copy quoted string)
  1070                          
  1071  92b4 c92a                     CMP   #'*'              ; compare with "*"
  1072  92b6 903d                     BCC   LAB_13EC          ; if < go save byte then continue crunching
  1073                          
  1074                                                        ; else crunch now
  1075                          LAB_13CC
  1076  92b8 2460                     BIT   Oquote            ; get open quote/DATA token flag
  1077  92ba 7039                     BVS   LAB_13EC          ; branch if b6 of Oquote set (was DATA)
  1078                                                        ; go save byte then continue crunching
  1079                          
  1080  92bc 8678                     STX   TempB             ; save buffer read index
  1081  92be 84ba                     STY   csidx             ; copy buffer save index
  1082  92c0 a040                     LDY   #<TAB_1STC        ; get keyword first character table low address
  1083  92c2 8473                     STY   ut2_pl            ; save pointer low byte
  1084  92c4 a0b3                     LDY   #>TAB_1STC        ; get keyword first character table high address
  1085  92c6 8474                     STY   ut2_ph            ; save pointer high byte
  1086  92c8 a000                     LDY   #$00              ; clear table pointer
  1087                          
  1088                          LAB_13D0
  1089  92ca d173                     CMP   (ut2_pl),Y        ; compare with keyword first character table byte
  1090  92cc f005                     BEQ   LAB_13D1          ; go do word_table_chr if match
  1091                          
  1092                          ; *** replace
  1093                          ;      BCC   LAB_13EA          ; if < keyword first character table byte go restore
  1094                          ; *** with
  1095  92ce 905b                     BCC   PATCH_LC2         ; if < keyword first character table byte go restore
  1096                          ; *** end
  1097                                                        ; Y and save to crunched
  1098                          
  1099  92d0 c8                       INY                     ; else increment pointer
  1100  92d1 d0f7                     BNE   LAB_13D0          ; and loop (branch always)
  1101                          
  1102                          ; have matched first character of some keyword
  1103                          
  1104                          LAB_13D1
  1105  92d3 98                       TYA                     ; copy matching index
  1106  92d4 0a                       ASL                     ; *2 (bytes per pointer)
  1107  92d5 aa                       TAX                     ; copy to new index
  1108  92d6 bd5eb3                   LDA   TAB_CHRT,X        ; get keyword table pointer low byte
  1109  92d9 8573                     STA   ut2_pl            ; save pointer low byte
  1110  92db bd5fb3                   LDA   TAB_CHRT+1,X      ; get keyword table pointer high byte
  1111  92de 8574                     STA   ut2_ph            ; save pointer high byte
  1112                          
  1113  92e0 a0ff                     LDY   #$FF              ; clear table pointer (make -1 for start)
  1114                          
  1115  92e2 a678                     LDX   TempB             ; restore buffer read index
  1116                          
  1117                          LAB_13D6
  1118  92e4 c8                       INY                     ; next table byte
  1119  92e5 b173                     LDA   (ut2_pl),Y        ; get byte from table
  1120                          LAB_13D8
  1121  92e7 300a                     BMI   LAB_13EA          ; all bytes matched so go save token
  1122                          
  1123  92e9 e8                       INX                     ; next buffer byte
  1124                          ; *** replace
  1125                          ;      CMP   Ibuffs,X          ; compare with byte from input buffer
  1126                          ; *** with
  1127  92ea 5d2103                   EOR     Ibuffs,x        ; check bits against table
  1128  92ed 29df                     AND     #$DF            ; DF masks the upper/lower case bit
  1129                          ; *** end      
  1130  92ef f0f3                     BEQ   LAB_13D6          ; go compare next if match
  1131                          
  1132  92f1 d02b                     BNE   LAB_1417          ; branch if >< (not found keyword)
  1133                          
  1134                          LAB_13EA
  1135  92f3 a4ba                     LDY   csidx             ; restore save index
  1136                          
  1137                                                        ; save crunched to output
  1138                          LAB_13EC
  1139  92f5 e8                       INX                     ; increment buffer index (to next input byte)
  1140  92f6 c8                       INY                     ; increment save index (to next output byte)
  1141  92f7 992103                   STA   Ibuffs,Y          ; save byte to output
  1142  92fa c900                     CMP   #$00              ; set the flags, set carry
  1143  92fc f032                     BEQ   LAB_142A          ; do exit if was null [EOL]
  1144                          
  1145                                                        ; A holds token or byte here
  1146  92fe e93a                     SBC   #':'              ; subtract ":" (carry set by CMP #00)
  1147  9300 f004                     BEQ   LAB_13FF          ; branch if it was ":" (is now $00)
  1148                          
  1149                                                        ; A now holds token-$3A
  1150  9302 c949                     CMP   #TK_DATA-$3A      ; compare with DATA token - $3A
  1151  9304 d002                     BNE   LAB_1401          ; branch if not DATA
  1152                          
  1153                                                        ; token was : or DATA
  1154                          LAB_13FF
  1155  9306 8560                     STA   Oquote            ; save token-$3A (clear for ":", TK_DATA-$3A for DATA)
  1156                          LAB_1401
  1157  9308 4957                     EOR   #TK_REM-$3A       ; effectively subtract REM token offset
  1158  930a d087                     BNE   LAB_13AC          ; If wasn't REM then go crunch rest of line
  1159                          
  1160  930c 855c                     STA   Asrch             ; else was REM so set search for [EOL]
  1161                          
  1162                                                        ; loop for REM, "..." etc.
  1163                          
  1164                          LAB_1408
  1165  930e bd2103                   LDA   Ibuffs,X          ; get byte from input buffer
  1166  9311 f0e2                     BEQ   LAB_13EC          ; branch if null [EOL]
  1167                          
  1168  9313 c55c                     CMP   Asrch             ; compare with stored character
  1169  9315 f0de                     BEQ   LAB_13EC          ; branch if match (end quote)
  1170                          
  1171                                                        ; entry for copy string in quotes, don't crunch
  1172                          LAB_1410
  1173  9317 c8                       INY                     ; increment buffer save index
  1174  9318 992103                   STA   Ibuffs,Y          ; save byte to output
  1175  931b e8                       INX                     ; increment buffer read index
  1176  931c d0f0                     BNE   LAB_1408          ; loop while <> 0 (should never be 0!)
  1177                          
  1178                                                        ; not found keyword this go
  1179                          LAB_1417
  1180  931e a678                     LDX   TempB             ; compare has failed, restore buffer index (start byte!)
  1181                          
  1182                                                        ; now find the end of this word in the table
  1183                          LAB_141B
  1184  9320 b173                     LDA   (ut2_pl),Y        ; get table byte
  1185  9322 08                       PHP                     ; save status
  1186  9323 c8                       INY                     ; increment table index
  1187  9324 28                       PLP                     ; restore byte status
  1188  9325 10f9                     BPL   LAB_141B          ; if not end of keyword go do next
  1189                          
  1190  9327 b173                     LDA   (ut2_pl),Y        ; get byte from keyword table
  1191  9329 d0bc                     BNE   LAB_13D8          ; go test next word if not zero byte (end of table)
  1192                          
  1193                                                        ; reached end of table with no match
  1194                          ; *** add label
  1195                          PATCH_LC2
  1196                          ; *** end
  1197                          ; *** end   patch: lower case token recognition V2 ***
  1198                          
  1199  932b bd2103                   LDA   Ibuffs,X          ; restore byte from input buffer
  1200  932e 10c3                     BPL   LAB_13EA          ; branch always (all bytes in buffer are $00-$7F)
  1201                                                        ; go save byte in output and continue crunching
  1202                          
  1203                                                        ; reached [EOL]
  1204                          LAB_142A
  1205  9330 c8                       INY                     ; increment pointer
  1206  9331 c8                       INY                     ; increment pointer (makes it next line pointer high byte)
  1207  9332 992103                   STA   Ibuffs,Y          ; save [EOL] (marks [EOT] in immediate mode)
  1208  9335 c8                       INY                     ; adjust for line copy
  1209  9336 c8                       INY                     ; adjust for line copy
  1210  9337 c8                       INY                     ; adjust for line copy
  1211  9338 c6c3                     DEC   Bpntrl            ; allow for increment (change if buffer starts at $xxFF)
  1212  933a 60                       RTS
  1213                          
  1214                          ; search Basic for temp integer line number from start of mem
  1215                          
  1216                          LAB_SSLN
  1217  933b a579               	LDA	Smeml			; get start of mem low byte
  1218  933d a67a               	LDX	Smemh			; get start of mem high byte
  1219                          
  1220                          ; search Basic for temp integer line number from AX
  1221                          ; returns carry set if found
  1222                          ; returns Baslnl/Baslnh pointer to found or next higher (not found) line
  1223                          
  1224                          ; old 541 new 507
  1225                          
  1226                          LAB_SHLN
  1227  933f a001               	LDY	#$01			; set index
  1228  9341 85aa               	STA	Baslnl		; save low byte as current
  1229  9343 86ab               	STX	Baslnh		; save high byte as current
  1230  9345 b1aa               	LDA	(Baslnl),Y		; get pointer high byte from addr
  1231  9347 f01a               	BEQ	LAB_145F		; pointer was zero so we're done, do 'not found' exit
  1232                          
  1233  9349 a003               	LDY	#$03			; set index to line # high byte
  1234  934b b1aa               	LDA	(Baslnl),Y		; get line # high byte
  1235  934d 88                 	DEY				; decrement index (point to low byte)
  1236  934e c512               	CMP	Itemph		; compare with temporary integer high byte
  1237  9350 d004               	BNE	LAB_1455		; if <> skip low byte check
  1238                          
  1239  9352 b1aa               	LDA	(Baslnl),Y		; get line # low byte
  1240  9354 c511               	CMP	Itempl		; compare with temporary integer low byte
  1241                          LAB_1455
  1242  9356 b009               	BCS	LAB_145E		; else if temp < this line, exit (passed line#)
  1243                          
  1244                          LAB_1456
  1245  9358 88                 	DEY				; decrement index to next line ptr high byte
  1246  9359 b1aa               	LDA	(Baslnl),Y		; get next line pointer high byte
  1247  935b aa                 	TAX				; copy to X
  1248  935c 88                 	DEY				; decrement index to next line ptr low byte
  1249  935d b1aa               	LDA	(Baslnl),Y		; get next line pointer low byte
  1250  935f 90de               	BCC	LAB_SHLN		; go search for line # in temp (Itempl/Itemph) from AX
  1251                          					; (carry always clear)
  1252                          
  1253                          LAB_145E
  1254  9361 f001               	BEQ	LAB_1460		; exit if temp = found line #, carry is set
  1255                          
  1256                          LAB_145F
  1257  9363 18                 	CLC				; clear found flag
  1258                          LAB_1460
  1259  9364 60                 	RTS
  1260                          
  1261                          ; perform NEW
  1262                          
  1263                          LAB_NEW
  1264  9365 d0fd               	BNE	LAB_1460		; exit if not end of statement (to do syntax error)
  1265                          
  1266                          LAB_1463
  1267  9367 a900               	LDA	#$00			; clear A
  1268  9369 a8                 	TAY				; clear Y
  1269  936a 9179               	STA	(Smeml),Y		; clear first line, next line pointer, low byte
  1270  936c c8                 	INY				; increment index
  1271  936d 9179               	STA	(Smeml),Y		; clear first line, next line pointer, high byte
  1272  936f 18                 	CLC				; clear carry
  1273  9370 a579               	LDA	Smeml			; get start of mem low byte
  1274  9372 6902               	ADC	#$02			; calculate end of BASIC low byte
  1275  9374 857b               	STA	Svarl			; save start of vars low byte
  1276  9376 a57a               	LDA	Smemh			; get start of mem high byte
  1277  9378 6900               	ADC	#$00			; add any carry
  1278  937a 857c               	STA	Svarh			; save start of vars high byte
  1279                          
  1280                          ; reset execution to start, clear vars and flush stack
  1281                          
  1282                          LAB_1477
  1283  937c 18                 	CLC				; clear carry
  1284  937d a579               	LDA	Smeml			; get start of mem low byte
  1285  937f 69ff               	ADC	#$FF			; -1
  1286  9381 85c3               	STA	Bpntrl		; save BASIC execute pointer low byte
  1287  9383 a57a               	LDA	Smemh			; get start of mem high byte
  1288  9385 69ff               	ADC	#$FF			; -1+carry
  1289  9387 85c4               	STA	Bpntrh		; save BASIC execute pointer high byte
  1290                          
  1291                          ; "CLEAR" command gets here
  1292                          
  1293                          LAB_147A
  1294  9389 a585               	LDA	Ememl			; get end of mem low byte
  1295  938b a486               	LDY	Ememh			; get end of mem high byte
  1296  938d 8581               	STA	Sstorl		; set bottom of string space low byte
  1297  938f 8482               	STY	Sstorh		; set bottom of string space high byte
  1298  9391 a57b               	LDA	Svarl			; get start of vars low byte
  1299  9393 a47c               	LDY	Svarh			; get start of vars high byte
  1300  9395 857d               	STA	Sarryl		; save var mem end low byte
  1301  9397 847e               	STY	Sarryh		; save var mem end high byte
  1302  9399 857f               	STA	Earryl		; save array mem end low byte
  1303  939b 8480               	STY	Earryh		; save array mem end high byte
  1304  939d 206095             	JSR	LAB_161A		; perform RESTORE command
  1305                          
  1306                          ; flush stack and clear continue flag
  1307                          
  1308                          LAB_1491
  1309  93a0 a268               	LDX	#des_sk		; set descriptor stack pointer
  1310  93a2 8665               	STX	next_s		; save descriptor stack pointer
  1311  93a4 68                 	PLA				; pull return address low byte
  1312  93a5 aa                 	TAX				; copy return address low byte
  1313  93a6 68                 	PLA				; pull return address high byte
  1314  93a7 8efe01             	STX	LAB_SKFE		; save to cleared stack
  1315  93aa 8dff01             	STA	LAB_SKFF		; save to cleared stack
  1316  93ad a2fd               	LDX	#$FD			; new stack pointer
  1317  93af 9a                 	TXS				; reset stack
  1318  93b0 a900               	LDA	#$00			; clear byte
  1319  93b2 858c               	STA	Cpntrh		; clear continue pointer high byte
  1320  93b4 8561               	STA	Sufnxf		; clear subscript/FNX flag
  1321                          LAB_14A6
  1322  93b6 60                 	RTS
  1323                          
  1324                          ; perform CLEAR
  1325                          
  1326                          LAB_CLEAR
  1327  93b7 f0d0               	BEQ	LAB_147A		; if no following token go do "CLEAR"
  1328                          
  1329                          					; else there was a following token (go do syntax error)
  1330  93b9 60                 	RTS
  1331                          
  1332                          ; perform LIST [n][-m]
  1333                          ; bigger, faster version (a _lot_ faster)
  1334                          
  1335                          LAB_LIST
  1336  93ba 9006               	BCC	LAB_14BD		; branch if next character numeric (LIST n..)
  1337                          
  1338  93bc f004               	BEQ	LAB_14BD		; branch if next character [NULL] (LIST)
  1339                          
  1340  93be c9b9               	CMP	#TK_MINUS		; compare with token for -
  1341  93c0 d0f4               	BNE	LAB_14A6		; exit if not - (LIST -m)
  1342                          
  1343                          					; LIST [[n][-m]]
  1344                          					; this bit sets the n , if present, as the start and end
  1345                          LAB_14BD
  1346  93c2 207197             	JSR	LAB_GFPN		; get fixed-point number into temp integer
  1347  93c5 203b93             	JSR	LAB_SSLN		; search BASIC for temp integer line number
  1348                          					; (pointer in Baslnl/Baslnh)
  1349  93c8 20c200             	JSR	LAB_GBYT		; scan memory
  1350  93cb f00c               	BEQ	LAB_14D4		; branch if no more characters
  1351                          
  1352                          					; this bit checks the - is present
  1353  93cd c9b9               	CMP	#TK_MINUS		; compare with token for -
  1354  93cf d093               	BNE	LAB_1460		; return if not "-" (will be Syntax error)
  1355                          
  1356                          					; LIST [n]-m
  1357                          					; the - was there so set m as the end value
  1358  93d1 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  1359  93d4 207197             	JSR	LAB_GFPN		; get fixed-point number into temp integer
  1360  93d7 d08b               	BNE	LAB_1460		; exit if not ok
  1361                          
  1362                          LAB_14D4
  1363  93d9 a511               	LDA	Itempl		; get temporary integer low byte
  1364  93db 0512               	ORA	Itemph		; OR temporary integer high byte
  1365  93dd d006               	BNE	LAB_14E2		; branch if start set
  1366                          
  1367  93df a9ff               	LDA	#$FF			; set for -1
  1368  93e1 8511               	STA	Itempl		; set temporary integer low byte
  1369  93e3 8512               	STA	Itemph		; set temporary integer high byte
  1370                          LAB_14E2
  1371  93e5 a001               	LDY	#$01			; set index for line
  1372  93e7 8460               	STY	Oquote		; clear open quote flag
  1373  93e9 20ae98             	JSR	LAB_CRLF		; print CR/LF
  1374  93ec b1aa               	LDA	(Baslnl),Y		; get next line pointer high byte
  1375                          					; pointer initially set by search at LAB_14BD
  1376  93ee f03e               	BEQ	LAB_152B		; if null all done so exit
  1377  93f0 202b95             	JSR	LAB_1629		; do CRTL-C check vector
  1378                          
  1379  93f3 c8                 	INY				; increment index for line
  1380  93f4 b1aa               	LDA	(Baslnl),Y		; get line # low byte
  1381  93f6 aa                 	TAX				; copy to X
  1382  93f7 c8                 	INY				; increment index
  1383  93f8 b1aa               	LDA	(Baslnl),Y		; get line # high byte
  1384  93fa c512               	CMP	Itemph		; compare with temporary integer high byte
  1385  93fc d004               	BNE	LAB_14FF		; branch if no high byte match
  1386                          
  1387  93fe e411               	CPX	Itempl		; compare with temporary integer low byte
  1388  9400 f002               	BEQ	LAB_1501		; branch if = last line to do (< will pass next branch)
  1389                          
  1390                          LAB_14FF				; else ..
  1391  9402 b02a               	BCS	LAB_152B		; if greater all done so exit
  1392                          
  1393                          LAB_1501
  1394  9404 8497               	STY	Tidx1			; save index for line
  1395  9406 2099aa             	JSR	LAB_295E		; print XA as unsigned integer
  1396  9409 a920               	LDA	#$20			; space is the next character
  1397                          LAB_1508
  1398  940b a497               	LDY	Tidx1			; get index for line
  1399  940d 297f               	AND	#$7F			; mask top out bit of character
  1400                          LAB_150C
  1401  940f 200499             	JSR	LAB_PRNA		; go print the character
  1402  9412 c922               	CMP	#$22			; was it " character
  1403  9414 d006               	BNE	LAB_1519		; branch if not
  1404                          
  1405                          					; we are either entering or leaving a pair of quotes
  1406  9416 a560               	LDA	Oquote		; get open quote flag
  1407  9418 49ff               	EOR	#$FF			; toggle it
  1408  941a 8560               	STA	Oquote		; save it back
  1409                          LAB_1519
  1410  941c c8                 	INY				; increment index
  1411  941d b1aa               	LDA	(Baslnl),Y		; get next byte
  1412  941f d00e               	BNE	LAB_152E		; branch if not [EOL] (go print character)
  1413  9421 a8                 	TAY				; else clear index
  1414  9422 b1aa               	LDA	(Baslnl),Y		; get next line pointer low byte
  1415  9424 aa                 	TAX				; copy to X
  1416  9425 c8                 	INY				; increment index
  1417  9426 b1aa               	LDA	(Baslnl),Y		; get next line pointer high byte
  1418  9428 86aa               	STX	Baslnl		; set pointer to line low byte
  1419  942a 85ab               	STA	Baslnh		; set pointer to line high byte
  1420  942c d0b7               	BNE	LAB_14E2		; go do next line if not [EOT]
  1421                          					; else ..
  1422                          LAB_152B
  1423  942e 60                 	RTS
  1424                          
  1425                          LAB_152E
  1426  942f 10de               	BPL	LAB_150C		; just go print it if not token byte
  1427                          
  1428                          					; else was token byte so uncrunch it (maybe)
  1429  9431 2460               	BIT	Oquote		; test the open quote flag
  1430  9433 30da               	BMI	LAB_150C		; just go print character if open quote set
  1431                          
  1432  9435 a2b5               	LDX	#>LAB_KEYT		; get table address high byte
  1433  9437 0a                 	ASL				; *2
  1434  9438 0a                 	ASL				; *4
  1435  9439 9002               	BCC	LAB_152F		; branch if no carry
  1436                          
  1437  943b e8                 	INX				; else increment high byte
  1438  943c 18                 	CLC				; clear carry for add
  1439                          LAB_152F
  1440  943d 694c               	ADC	#<LAB_KEYT		; add low byte
  1441  943f 9001               	BCC	LAB_1530		; branch if no carry
  1442                          
  1443  9441 e8                 	INX				; else increment high byte
  1444                          LAB_1530
  1445  9442 8573               	STA	ut2_pl		; save table pointer low byte
  1446  9444 8674               	STX	ut2_ph		; save table pointer high byte
  1447  9446 8497               	STY	Tidx1			; save index for line
  1448  9448 a000               	LDY	#$00			; clear index
  1449  944a b173               	LDA	(ut2_pl),Y		; get length
  1450  944c aa                 	TAX				; copy length
  1451  944d c8                 	INY				; increment index
  1452  944e b173               	LDA	(ut2_pl),Y		; get 1st character
  1453  9450 ca                 	DEX				; decrement length
  1454  9451 f0b8               	BEQ	LAB_1508		; if no more characters exit and print
  1455                          
  1456  9453 200499             	JSR	LAB_PRNA		; go print the character
  1457  9456 c8                 	INY				; increment index
  1458  9457 b173               	LDA	(ut2_pl),Y		; get keyword address low byte
  1459  9459 48                 	PHA				; save it for now
  1460  945a c8                 	INY				; increment index
  1461  945b b173               	LDA	(ut2_pl),Y		; get keyword address high byte
  1462  945d a000               	LDY	#$00
  1463  945f 8574               	STA	ut2_ph		; save keyword pointer high byte
  1464  9461 68                 	PLA				; pull low byte
  1465  9462 8573               	STA	ut2_pl		; save keyword pointer low byte
  1466                          LAB_1540
  1467  9464 b173               	LDA	(ut2_pl),Y		; get character
  1468  9466 ca                 	DEX				; decrement character count
  1469  9467 f0a2               	BEQ	LAB_1508		; if last character exit and print
  1470                          
  1471  9469 200499             	JSR	LAB_PRNA		; go print the character
  1472  946c c8                 	INY				; increment index
  1473  946d d0f5               	BNE	LAB_1540		; loop for next character
  1474                          
  1475                          ; perform FOR
  1476                          
  1477                          LAB_FOR
  1478  946f a980               	LDA	#$80			; set FNX
  1479  9471 8561               	STA	Sufnxf		; set subscript/FNX flag
  1480  9473 20d097             	JSR	LAB_LET		; go do LET
  1481  9476 68                 	PLA				; pull return address
  1482  9477 68                 	PLA				; pull return address
  1483  9478 a910               	LDA	#$10			; we need 16d bytes !
  1484  947a 200e91             	JSR	LAB_1212		; check room on stack for A bytes
  1485  947d 20b996             	JSR	LAB_SNBS		; scan for next BASIC statement ([:] or [EOL])
  1486  9480 18                 	CLC				; clear carry for add
  1487  9481 98                 	TYA				; copy index to A
  1488  9482 65c3               	ADC	Bpntrl		; add BASIC execute pointer low byte
  1489  9484 48                 	PHA				; push onto stack
  1490  9485 a5c4               	LDA	Bpntrh		; get BASIC execute pointer high byte
  1491  9487 6900               	ADC	#$00			; add carry
  1492  9489 48                 	PHA				; push onto stack
  1493  948a a588               	LDA	Clineh		; get current line high byte
  1494  948c 48                 	PHA				; push onto stack
  1495  948d a587               	LDA	Clinel		; get current line low byte
  1496  948f 48                 	PHA				; push onto stack
  1497  9490 a9af               	LDA	#TK_TO		; get "TO" token
  1498  9492 20089c             	JSR	LAB_SCCA		; scan for CHR$(A) , else do syntax error then warm start
  1499  9495 20e79a             	JSR	LAB_CTNM		; check if source is numeric, else do type mismatch
  1500  9498 20e49a             	JSR	LAB_EVNM		; evaluate expression and check is numeric,
  1501                          					; else do type mismatch
  1502  949b a5b0               	LDA	FAC1_s		; get FAC1 sign (b7)
  1503  949d 097f               	ORA	#$7F			; set all non sign bits
  1504  949f 25ad               	AND	FAC1_1		; and FAC1 mantissa1
  1505  94a1 85ad               	STA	FAC1_1		; save FAC1 mantissa1
  1506  94a3 a9ae               	LDA	#<LAB_159F		; set return address low byte
  1507  94a5 a094               	LDY	#>LAB_159F		; set return address high byte
  1508  94a7 8571               	STA	ut1_pl		; save return address low byte
  1509  94a9 8472               	STY	ut1_ph		; save return address high byte
  1510  94ab 4c9b9b             	JMP	LAB_1B66		; round FAC1 and put on stack (returns to next instruction)
  1511                          
  1512                          LAB_159F
  1513  94ae a90c               	LDA	#<LAB_259C		; set 1 pointer low addr (default step size)
  1514  94b0 a0b2               	LDY	#>LAB_259C		; set 1 pointer high addr
  1515  94b2 2094a8             	JSR	LAB_UFAC		; unpack memory (AY) into FAC1
  1516  94b5 20c200             	JSR	LAB_GBYT		; scan memory
  1517  94b8 c9b4               	CMP	#TK_STEP		; compare with STEP token
  1518  94ba d006               	BNE	LAB_15B3		; jump if not "STEP"
  1519                          
  1520                          					;.was step so ..
  1521  94bc 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  1522  94bf 20e49a             	JSR	LAB_EVNM		; evaluate expression and check is numeric,
  1523                          					; else do type mismatch
  1524                          LAB_15B3
  1525  94c2 2000a9             	JSR	LAB_27CA		; return A=FF,C=1/-ve A=01,C=0/+ve
  1526  94c5 85b0               	STA	FAC1_s		; set FAC1 sign (b7)
  1527                          					; this is +1 for +ve step and -1 for -ve step, in NEXT we
  1528                          					; compare the FOR value and the TO value and return +1 if
  1529                          					; FOR > TO, 0 if FOR = TO and -1 if FOR < TO. the value
  1530                          					; here (+/-1) is then compared to that result and if they
  1531                          					; are the same (+ve and FOR > TO or -ve and FOR < TO) then
  1532                          					; the loop is done
  1533  94c7 20909b             	JSR	LAB_1B5B		; push sign, round FAC1 and put on stack
  1534  94ca a598               	LDA	Frnxth		; get var pointer for FOR/NEXT high byte
  1535  94cc 48                 	PHA				; push on stack
  1536  94cd a597               	LDA	Frnxtl		; get var pointer for FOR/NEXT low byte
  1537  94cf 48                 	PHA				; push on stack
  1538  94d0 a981               	LDA	#TK_FOR		; get FOR token
  1539  94d2 48                 	PHA				; push on stack
  1540                          
  1541                          ; interpreter inner loop
  1542                          
  1543                          LAB_15C2
  1544  94d3 202b95             	JSR	LAB_1629		; do CRTL-C check vector
  1545  94d6 a5c3               	LDA	Bpntrl		; get BASIC execute pointer low byte
  1546  94d8 a4c4               	LDY	Bpntrh		; get BASIC execute pointer high byte
  1547                          
  1548  94da a688               	LDX	Clineh		; continue line is $FFxx for immediate mode
  1549                          					; ($00xx for RUN from immediate mode)
  1550  94dc e8                 	INX				; increment it (now $00 if immediate mode)
  1551  94dd f004               	BEQ	LAB_15D1		; branch if null (immediate mode)
  1552                          
  1553  94df 858b               	STA	Cpntrl		; save continue pointer low byte
  1554  94e1 848c               	STY	Cpntrh		; save continue pointer high byte
  1555                          LAB_15D1
  1556  94e3 a000               	LDY	#$00			; clear index
  1557  94e5 b1c3               	LDA	(Bpntrl),Y		; get next byte
  1558  94e7 f007               	BEQ	LAB_15DC		; branch if null [EOL]
  1559                          
  1560  94e9 c93a               	CMP	#':'			; compare with ":"
  1561  94eb f01d               	BEQ	LAB_15F6		; branch if = (statement separator)
  1562                          
  1563                          LAB_15D9
  1564  94ed 4c199c             	JMP	LAB_SNER		; else syntax error then warm start
  1565                          
  1566                          					; have reached [EOL]
  1567                          LAB_15DC
  1568  94f0 a002               	LDY	#$02			; set index
  1569  94f2 b1c3               	LDA	(Bpntrl),Y		; get next line pointer high byte
  1570  94f4 18                 	CLC				; clear carry for no "BREAK" message
  1571  94f5 f056               	BEQ	LAB_1651		; if null go to immediate mode (was immediate or [EOT]
  1572                          					; marker)
  1573                          
  1574  94f7 c8                 	INY				; increment index
  1575  94f8 b1c3               	LDA	(Bpntrl),Y		; get line # low byte
  1576  94fa 8587               	STA	Clinel		; save current line low byte
  1577  94fc c8                 	INY				; increment index
  1578  94fd b1c3               	LDA	(Bpntrl),Y		; get line # high byte
  1579  94ff 8588               	STA	Clineh		; save current line high byte
  1580  9501 98                 	TYA				; A now = 4
  1581  9502 65c3               	ADC	Bpntrl		; add BASIC execute pointer low byte
  1582  9504 85c3               	STA	Bpntrl		; save BASIC execute pointer low byte
  1583  9506 9002               	BCC	LAB_15F6		; branch if no overflow
  1584                          
  1585  9508 e6c4               	INC	Bpntrh		; else increment BASIC execute pointer high byte
  1586                          LAB_15F6
  1587  950a 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  1588                          
  1589                          LAB_15F9
  1590  950d 201395             	JSR	LAB_15FF		; go interpret BASIC code from (Bpntrl)
  1591                          
  1592                          LAB_15FC
  1593  9510 4cd394             	JMP	LAB_15C2		; loop
  1594                          
  1595                          ; interpret BASIC code from (Bpntrl)
  1596                          
  1597                          LAB_15FF
  1598  9513 f059               	BEQ	LAB_1628		; exit if zero [EOL]
  1599                          
  1600                          LAB_1602
  1601  9515 0a                 	ASL				; *2 bytes per vector and normalise token
  1602  9516 b003               	BCS	LAB_1609		; branch if was token
  1603                          
  1604  9518 4cd097             	JMP	LAB_LET		; else go do implied LET
  1605                          
  1606                          LAB_1609
  1607  951b c95a               	CMP	#(TK_TAB-$80)*2	; compare normalised token * 2 with TAB
  1608  951d b0ce               	BCS	LAB_15D9		; branch if A>=TAB (do syntax error then warm start)
  1609                          					; only tokens before TAB can start a line
  1610  951f a8                 	TAY				; copy to index
  1611  9520 b934b2             	LDA	LAB_CTBL+1,Y	; get vector high byte
  1612  9523 48                 	PHA				; onto stack
  1613  9524 b933b2             	LDA	LAB_CTBL,Y		; get vector low byte
  1614  9527 48                 	PHA				; onto stack
  1615  9528 4cbc00             	JMP	LAB_IGBY		; jump to increment and scan memory
  1616                          					; then "return" to vector
  1617                          
  1618                          ; CTRL-C check jump. this is called as a subroutine but exits back via a jump if a
  1619                          ; key press is detected.
  1620                          
  1621                          LAB_1629
  1622  952b 6c0303             	JMP	(VEC_CC)		; ctrl c check vector
  1623                          
  1624                          ; if there was a key press it gets back here ..
  1625                          
  1626                          LAB_1636
  1627  952e c903               	CMP	#$03			; compare with CTRL-C
  1628                          
  1629                          ; perform STOP
  1630                          
  1631                          LAB_STOP
  1632  9530 b001               	BCS	LAB_163B		; branch if token follows STOP
  1633                          					; else just END
  1634                          ; END
  1635                          
  1636                          LAB_END
  1637  9532 18                 	CLC				; clear the carry, indicate a normal program end
  1638                          LAB_163B
  1639  9533 d06c               	BNE	LAB_167A		; if wasn't CTRL-C or there is a following byte return
  1640                          
  1641  9535 a5c4               	LDA	Bpntrh		; get the BASIC execute pointer high byte
  1642  9537 4903               	EOR	#>Ibuffs		; compare with buffer address high byte (Cb unchanged)
  1643  9539 f010               	BEQ	LAB_164F		; branch if the BASIC pointer is in the input buffer
  1644                          					; (can't continue in immediate mode)
  1645                          
  1646                          					; else ..
  1647  953b 4903               	EOR	#>Ibuffs		; correct the bits
  1648  953d a4c3               	LDY	Bpntrl		; get BASIC execute pointer low byte
  1649  953f 848b               	STY	Cpntrl		; save continue pointer low byte
  1650  9541 858c               	STA	Cpntrh		; save continue pointer high byte
  1651                          LAB_1647
  1652  9543 a587               	LDA	Clinel		; get current line low byte
  1653  9545 a488               	LDY	Clineh		; get current line high byte
  1654  9547 8589               	STA	Blinel		; save break line low byte
  1655  9549 848a               	STY	Blineh		; save break line high byte
  1656                          LAB_164F
  1657  954b 68                 	PLA				; pull return address low
  1658  954c 68                 	PLA				; pull return address high
  1659                          LAB_1651
  1660  954d 08                 	php
  1661  954e 2025c9             	jsr hbc56SetupDisplay
  1662  9551 28                 	plp
  1663  9552 9007               	BCC	LAB_165E		; if was program end just do warm start
  1664                          
  1665                          					; else ..
  1666  9554 a933               	LDA	#<LAB_BMSG		; point to "Break" low byte
  1667  9556 a0b8               	LDY	#>LAB_BMSG		; point to "Break" high byte
  1668  9558 4c5a91             	JMP	LAB_1269		; print "Break" and do warm start
  1669                          
  1670                          LAB_165E
  1671  955b 4c6591             	JMP	LAB_1274		; go do warm start
  1672                          
  1673                          ; perform RESTORE
  1674                          
  1675                          LAB_RESTORE
  1676  955e d00f               	BNE	LAB_RESTOREn	; branch if next character not null (RESTORE n)
  1677                          
  1678                          LAB_161A
  1679  9560 38                 	SEC				; set carry for subtract
  1680  9561 a579               	LDA	Smeml			; get start of mem low byte
  1681  9563 e901               	SBC	#$01			; -1
  1682  9565 a47a               	LDY	Smemh			; get start of mem high byte
  1683  9567 b001               	BCS	LAB_1624		; branch if no underflow
  1684                          
  1685                          LAB_uflow
  1686  9569 88                 	DEY				; else decrement high byte
  1687                          LAB_1624
  1688  956a 858f               	STA	Dptrl			; save DATA pointer low byte
  1689  956c 8490               	STY	Dptrh			; save DATA pointer high byte
  1690                          LAB_1628
  1691  956e 60                 	RTS
  1692                          
  1693                          					; is RESTORE n
  1694                          LAB_RESTOREn
  1695  956f 207197             	JSR	LAB_GFPN		; get fixed-point number into temp integer
  1696  9572 20bc96             	JSR	LAB_SNBL		; scan for next BASIC line
  1697  9575 a588               	LDA	Clineh		; get current line high byte
  1698  9577 c512               	CMP	Itemph		; compare with temporary integer high byte
  1699  9579 b00b               	BCS	LAB_reset_search	; branch if >= (start search from beginning)
  1700                          
  1701  957b 98                 	TYA				; else copy line index to A
  1702  957c 38                 	SEC				; set carry (+1)
  1703  957d 65c3               	ADC	Bpntrl		; add BASIC execute pointer low byte
  1704  957f a6c4               	LDX	Bpntrh		; get BASIC execute pointer high byte
  1705  9581 9007               	BCC	LAB_go_search	; branch if no overflow to high byte
  1706                          
  1707  9583 e8                 	INX				; increment high byte
  1708  9584 b004               	BCS	LAB_go_search	; branch always (can never be carry clear)
  1709                          
  1710                          ; search for line # in temp (Itempl/Itemph) from start of mem pointer (Smeml)
  1711                          
  1712                          LAB_reset_search
  1713  9586 a579               	LDA	Smeml			; get start of mem low byte
  1714  9588 a67a               	LDX	Smemh			; get start of mem high byte
  1715                          
  1716                          ; search for line # in temp (Itempl/Itemph) from (AX)
  1717                          
  1718                          LAB_go_search
  1719                          
  1720  958a 203f93             	JSR	LAB_SHLN		; search Basic for temp integer line number from AX
  1721  958d b003               	BCS	LAB_line_found	; if carry set go set pointer
  1722                          
  1723  958f 4c8e96             	JMP	LAB_16F7		; else go do "Undefined statement" error
  1724                          
  1725                          LAB_line_found
  1726                          					; carry already set for subtract
  1727  9592 a5aa               	LDA	Baslnl		; get pointer low byte
  1728  9594 e901               	SBC	#$01			; -1
  1729  9596 a4ab               	LDY	Baslnh		; get pointer high byte
  1730  9598 b0d0               	BCS	LAB_1624		; branch if no underflow (save DATA pointer and return)
  1731                          
  1732  959a 90cd               	BCC	LAB_uflow		; else decrement high byte then save DATA pointer and
  1733                          					; return (branch always)
  1734                          
  1735                          ; perform NULL
  1736                          
  1737                          LAB_NULL
  1738  959c 20a3a4             	JSR	LAB_GTBY		; get byte parameter
  1739  959f 860d               	STX	Nullct		; save new NULL count
  1740                          LAB_167A
  1741  95a1 60                 	RTS
  1742                          
  1743                          ; perform CONT
  1744                          
  1745                          LAB_CONT
  1746  95a2 d0fd               	BNE	LAB_167A		; if following byte exit to do syntax error
  1747                          
  1748  95a4 a48c               	LDY	Cpntrh		; get continue pointer high byte
  1749  95a6 d005               	BNE	LAB_166C		; go do continue if we can
  1750                          
  1751  95a8 a21e               	LDX	#$1E			; error code $1E ("Can't continue" error)
  1752  95aa 4c4791             	JMP	LAB_XERR		; do error #X, then warm start
  1753                          
  1754                          					; we can continue so ..
  1755                          LAB_166C
  1756  95ad a993               	LDA	#TK_ON		; set token for ON
  1757  95af 202baf             	JSR	LAB_IRQ		; set IRQ flags
  1758  95b2 a993               	LDA	#TK_ON		; set token for ON
  1759  95b4 202eaf             	JSR	LAB_NMI		; set NMI flags
  1760                          
  1761  95b7 84c4               	STY	Bpntrh		; save BASIC execute pointer high byte
  1762  95b9 a58b               	LDA	Cpntrl		; get continue pointer low byte
  1763  95bb 85c3               	STA	Bpntrl		; save BASIC execute pointer low byte
  1764  95bd a589               	LDA	Blinel		; get break line low byte
  1765  95bf a48a               	LDY	Blineh		; get break line high byte
  1766  95c1 8587               	STA	Clinel		; set current line low byte
  1767  95c3 8488               	STY	Clineh		; set current line high byte
  1768  95c5 60                 	RTS
  1769                          
  1770                          ; perform RUN
  1771                          
  1772                          LAB_RUN
  1773  95c6 d003               	BNE	LAB_1696		; branch if RUN n
  1774  95c8 4c7c93             	JMP	LAB_1477		; reset execution to start, clear variables, flush stack and
  1775                          					; return
  1776                          
  1777                          ; does RUN n
  1778                          
  1779                          LAB_1696
  1780  95cb 208993             	JSR	LAB_147A		; go do "CLEAR"
  1781  95ce f02e               	BEQ	LAB_16B0		; get n and do GOTO n (branch always as CLEAR sets Z=1)
  1782                          
  1783                          ; perform DO
  1784                          
  1785                          LAB_DO
  1786  95d0 a905               	LDA	#$05			; need 5 bytes for DO
  1787  95d2 200e91             	JSR	LAB_1212		; check room on stack for A bytes
  1788  95d5 a5c4               	LDA	Bpntrh		; get BASIC execute pointer high byte
  1789  95d7 48                 	PHA				; push on stack
  1790  95d8 a5c3               	LDA	Bpntrl		; get BASIC execute pointer low byte
  1791  95da 48                 	PHA				; push on stack
  1792  95db a588               	LDA	Clineh		; get current line high byte
  1793  95dd 48                 	PHA				; push on stack
  1794  95de a587               	LDA	Clinel		; get current line low byte
  1795  95e0 48                 	PHA				; push on stack
  1796  95e1 a99f               	LDA	#TK_DO		; token for DO
  1797  95e3 48                 	PHA				; push on stack
  1798  95e4 20c200             	JSR	LAB_GBYT		; scan memory
  1799  95e7 4cd394             	JMP	LAB_15C2		; go do interpreter inner loop
  1800                          
  1801                          ; perform GOSUB
  1802                          
  1803                          LAB_GOSUB
  1804  95ea a905               	LDA	#$05			; need 5 bytes for GOSUB
  1805  95ec 200e91             	JSR	LAB_1212		; check room on stack for A bytes
  1806  95ef a5c4               	LDA	Bpntrh		; get BASIC execute pointer high byte
  1807  95f1 48                 	PHA				; push on stack
  1808  95f2 a5c3               	LDA	Bpntrl		; get BASIC execute pointer low byte
  1809  95f4 48                 	PHA				; push on stack
  1810  95f5 a588               	LDA	Clineh		; get current line high byte
  1811  95f7 48                 	PHA				; push on stack
  1812  95f8 a587               	LDA	Clinel		; get current line low byte
  1813  95fa 48                 	PHA				; push on stack
  1814  95fb a98d               	LDA	#TK_GOSUB		; token for GOSUB
  1815  95fd 48                 	PHA				; push on stack
  1816                          LAB_16B0
  1817  95fe 20c200             	JSR	LAB_GBYT		; scan memory
  1818  9601 200796             	JSR	LAB_GOTO		; perform GOTO n
  1819  9604 4cd394             	JMP	LAB_15C2		; go do interpreter inner loop
  1820                          					; (can't RTS, we used the stack!)
  1821                          
  1822                          ; perform GOTO
  1823                          
  1824                          LAB_GOTO
  1825  9607 207197             	JSR	LAB_GFPN		; get fixed-point number into temp integer
  1826  960a 20bc96             	JSR	LAB_SNBL		; scan for next BASIC line
  1827  960d a588               	LDA	Clineh		; get current line high byte
  1828  960f c512               	CMP	Itemph		; compare with temporary integer high byte
  1829  9611 b00b               	BCS	LAB_16D0		; branch if >= (start search from beginning)
  1830                          
  1831  9613 98                 	TYA				; else copy line index to A
  1832  9614 38                 	SEC				; set carry (+1)
  1833  9615 65c3               	ADC	Bpntrl		; add BASIC execute pointer low byte
  1834  9617 a6c4               	LDX	Bpntrh		; get BASIC execute pointer high byte
  1835  9619 9007               	BCC	LAB_16D4		; branch if no overflow to high byte
  1836                          
  1837  961b e8                 	INX				; increment high byte
  1838  961c b004               	BCS	LAB_16D4		; branch always (can never be carry)
  1839                          
  1840                          ; search for line # in temp (Itempl/Itemph) from start of mem pointer (Smeml)
  1841                          
  1842                          LAB_16D0
  1843  961e a579               	LDA	Smeml			; get start of mem low byte
  1844  9620 a67a               	LDX	Smemh			; get start of mem high byte
  1845                          
  1846                          ; search for line # in temp (Itempl/Itemph) from (AX)
  1847                          
  1848                          LAB_16D4
  1849  9622 203f93             	JSR	LAB_SHLN		; search Basic for temp integer line number from AX
  1850  9625 9067               	BCC	LAB_16F7		; if carry clear go do "Undefined statement" error
  1851                          					; (unspecified statement)
  1852                          
  1853                          					; carry already set for subtract
  1854  9627 a5aa               	LDA	Baslnl		; get pointer low byte
  1855  9629 e901               	SBC	#$01			; -1
  1856  962b 85c3               	STA	Bpntrl		; save BASIC execute pointer low byte
  1857  962d a5ab               	LDA	Baslnh		; get pointer high byte
  1858  962f e900               	SBC	#$00			; subtract carry
  1859  9631 85c4               	STA	Bpntrh		; save BASIC execute pointer high byte
  1860                          LAB_16E5
  1861  9633 60                 	RTS
  1862                          
  1863                          LAB_DONOK
  1864  9634 a222               	LDX	#$22			; error code $22 ("LOOP without DO" error)
  1865  9636 4c4791             	JMP	LAB_XERR		; do error #X, then warm start
  1866                          
  1867                          ; perform LOOP
  1868                          
  1869                          LAB_LOOP
  1870  9639 a8                 	TAY				; save following token
  1871  963a ba                 	TSX				; copy stack pointer
  1872  963b bd0301             	LDA	LAB_STAK+3,X	; get token byte from stack
  1873  963e c99f               	CMP	#TK_DO		; compare with DO token
  1874  9640 d0f2               	BNE	LAB_DONOK		; branch if no matching DO
  1875                          
  1876  9642 e8                 	INX				; dump calling routine return address
  1877  9643 e8                 	INX				; dump calling routine return address
  1878  9644 9a                 	TXS				; correct stack
  1879  9645 98                 	TYA				; get saved following token back
  1880  9646 f020               	BEQ	LoopAlways		; if no following token loop forever
  1881                          					; (stack pointer in X)
  1882                          
  1883  9648 c93a               	CMP	#':'			; could be ':'
  1884  964a f01c               	BEQ	LoopAlways		; if :... loop forever
  1885                          
  1886  964c e9b5               	SBC	#TK_UNTIL		; subtract token for UNTIL, we know carry is set here
  1887  964e aa                 	TAX				; copy to X (if it was UNTIL then Y will be correct)
  1888  964f f004               	BEQ	DoRest		; branch if was UNTIL
  1889                          
  1890  9651 ca                 	DEX				; decrement result
  1891  9652 d062               	BNE	LAB_16FC		; if not WHILE go do syntax error and warm start
  1892                          					; only if the token was WHILE will this fail
  1893                          
  1894  9654 ca                 	DEX				; set invert result byte
  1895                          DoRest
  1896  9655 8698               	STX	Frnxth		; save invert result byte
  1897  9657 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  1898  965a 20f89a             	JSR	LAB_EVEX		; evaluate expression
  1899  965d a5ac               	LDA	FAC1_e		; get FAC1 exponent
  1900  965f f002               	BEQ	DoCmp			; if =0 go do straight compare
  1901                          
  1902  9661 a9ff               	LDA	#$FF			; else set all bits
  1903                          DoCmp
  1904  9663 ba                 	TSX				; copy stack pointer
  1905  9664 4598               	EOR	Frnxth		; EOR with invert byte
  1906  9666 d01a               	BNE	LoopDone		; if <> 0 clear stack and back to interpreter loop
  1907                          
  1908                          					; loop condition wasn't met so do it again
  1909                          LoopAlways
  1910  9668 bd0201             	LDA	LAB_STAK+2,X	; get current line low byte
  1911  966b 8587               	STA	Clinel		; save current line low byte
  1912  966d bd0301             	LDA	LAB_STAK+3,X	; get current line high byte
  1913  9670 8588               	STA	Clineh		; save current line high byte
  1914  9672 bd0401             	LDA	LAB_STAK+4,X	; get BASIC execute pointer low byte
  1915  9675 85c3               	STA	Bpntrl		; save BASIC execute pointer low byte
  1916  9677 bd0501             	LDA	LAB_STAK+5,X	; get BASIC execute pointer high byte
  1917  967a 85c4               	STA	Bpntrh		; save BASIC execute pointer high byte
  1918  967c 20c200             	JSR	LAB_GBYT		; scan memory
  1919  967f 4cd394             	JMP	LAB_15C2		; go do interpreter inner loop
  1920                          
  1921                          					; clear stack and back to interpreter loop
  1922                          LoopDone
  1923  9682 e8                 	INX				; dump DO token
  1924  9683 e8                 	INX				; dump current line low byte
  1925  9684 e8                 	INX				; dump current line high byte
  1926  9685 e8                 	INX				; dump BASIC execute pointer low byte
  1927  9686 e8                 	INX				; dump BASIC execute pointer high byte
  1928  9687 9a                 	TXS				; correct stack
  1929  9688 4ca896             	JMP	LAB_DATA		; go perform DATA (find : or [EOL])
  1930                          
  1931                          ; do the return without gosub error
  1932                          
  1933                          LAB_16F4
  1934  968b a204               	LDX	#$04			; error code $04 ("RETURN without GOSUB" error)
  1935  968d 2c                 	!text	$2C			; makes next line BIT LAB_0EA2
  1936                          
  1937                          LAB_16F7				; do undefined statement error
  1938  968e a20e               	LDX	#$0E			; error code $0E ("Undefined statement" error)
  1939  9690 4c4791             	JMP	LAB_XERR		; do error #X, then warm start
  1940                          
  1941                          ; perform RETURN
  1942                          
  1943                          LAB_RETURN
  1944  9693 d09e               	BNE	LAB_16E5		; exit if following token (to allow syntax error)
  1945                          
  1946                          LAB_16E8
  1947  9695 68                 	PLA				; dump calling routine return address
  1948  9696 68                 	PLA				; dump calling routine return address
  1949  9697 68                 	PLA				; pull token
  1950  9698 c98d               	CMP	#TK_GOSUB		; compare with GOSUB token
  1951  969a d0ef               	BNE	LAB_16F4		; branch if no matching GOSUB
  1952                          
  1953                          LAB_16FF
  1954  969c 68                 	PLA				; pull current line low byte
  1955  969d 8587               	STA	Clinel		; save current line low byte
  1956  969f 68                 	PLA				; pull current line high byte
  1957  96a0 8588               	STA	Clineh		; save current line high byte
  1958  96a2 68                 	PLA				; pull BASIC execute pointer low byte
  1959  96a3 85c3               	STA	Bpntrl		; save BASIC execute pointer low byte
  1960  96a5 68                 	PLA				; pull BASIC execute pointer high byte
  1961  96a6 85c4               	STA	Bpntrh		; save BASIC execute pointer high byte
  1962                          
  1963                          					; now do the DATA statement as we could be returning into
  1964                          					; the middle of an ON <var> GOSUB n,m,p,q line
  1965                          					; (the return address used by the DATA statement is the one
  1966                          					; pushed before the GOSUB was executed!)
  1967                          
  1968                          ; perform DATA
  1969                          
  1970                          LAB_DATA
  1971  96a8 20b996             	JSR	LAB_SNBS		; scan for next BASIC statement ([:] or [EOL])
  1972                          
  1973                          					; set BASIC execute pointer
  1974                          LAB_170F
  1975  96ab 98                 	TYA				; copy index to A
  1976  96ac 18                 	CLC				; clear carry for add
  1977  96ad 65c3               	ADC	Bpntrl		; add BASIC execute pointer low byte
  1978  96af 85c3               	STA	Bpntrl		; save BASIC execute pointer low byte
  1979  96b1 9002               	BCC	LAB_1719		; skip next if no carry
  1980                          
  1981  96b3 e6c4               	INC	Bpntrh		; else increment BASIC execute pointer high byte
  1982                          LAB_1719
  1983  96b5 60                 	RTS
  1984                          
  1985                          LAB_16FC
  1986  96b6 4c199c             	JMP	LAB_SNER		; do syntax error then warm start
  1987                          
  1988                          ; scan for next BASIC statement ([:] or [EOL])
  1989                          ; returns Y as index to [:] or [EOL]
  1990                          
  1991                          LAB_SNBS
  1992  96b9 a23a               	LDX	#':'			; set look for character = ":"
  1993  96bb 2c                 	!text	$2C			; makes next line BIT $00A2
  1994                          
  1995                          ; scan for next BASIC line
  1996                          ; returns Y as index to [EOL]
  1997                          
  1998                          LAB_SNBL
  1999  96bc a200               	LDX	#$00			; set alt search character = [EOL]
  2000  96be a000               	LDY	#$00			; set search character = [EOL]
  2001  96c0 845c               	STY	Asrch			; store search character
  2002                          LAB_1725
  2003  96c2 8a                 	TXA				; get alt search character
  2004  96c3 455c               	EOR	Asrch			; toggle search character, effectively swap with $00
  2005  96c5 855c               	STA	Asrch			; save swapped search character
  2006                          LAB_172D
  2007  96c7 b1c3               	LDA	(Bpntrl),Y		; get next byte
  2008  96c9 f0ea               	BEQ	LAB_1719		; exit if null [EOL]
  2009                          
  2010  96cb c55c               	CMP	Asrch			; compare with search character
  2011  96cd f0e6               	BEQ	LAB_1719		; exit if found
  2012                          
  2013  96cf c8                 	INY				; increment index
  2014  96d0 c922               	CMP	#$22			; compare current character with open quote
  2015  96d2 d0f3               	BNE	LAB_172D		; if not open quote go get next character
  2016                          
  2017  96d4 f0ec               	BEQ	LAB_1725		; if found go swap search character for alt search character
  2018                          
  2019                          ; perform IF
  2020                          
  2021                          LAB_IF
  2022  96d6 20f89a             	JSR	LAB_EVEX		; evaluate the expression
  2023  96d9 20c200             	JSR	LAB_GBYT		; scan memory
  2024  96dc c9b2               	CMP	#TK_THEN		; compare with THEN token
  2025  96de f011               	BEQ	LAB_174B		; if it was THEN go do IF
  2026                          
  2027                          					; wasn't IF .. THEN so must be IF .. GOTO
  2028  96e0 c989               	CMP	#TK_GOTO		; compare with GOTO token
  2029  96e2 d0d2               	BNE	LAB_16FC		; if it wasn't GOTO go do syntax error
  2030                          
  2031  96e4 a6c3               	LDX	Bpntrl		; save the basic pointer low byte
  2032  96e6 a4c4               	LDY	Bpntrh		; save the basic pointer high byte
  2033  96e8 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  2034  96eb b0c9               	BCS	LAB_16FC		; if not numeric go do syntax error
  2035                          
  2036  96ed 86c3               	STX	Bpntrl		; restore the basic pointer low byte
  2037  96ef 84c4               	STY	Bpntrh		; restore the basic pointer high byte
  2038                          LAB_174B
  2039  96f1 a5ac               	LDA	FAC1_e		; get FAC1 exponent
  2040  96f3 f01b               	BEQ	LAB_174E		; if the result was zero go look for an ELSE
  2041                          
  2042  96f5 20bc00             	JSR	LAB_IGBY		; else increment and scan memory
  2043  96f8 b003               	BCS	LAB_174D		; if not numeric go do var or keyword
  2044                          
  2045                          LAB_174C
  2046  96fa 4c0796             	JMP	LAB_GOTO		; else was numeric so do GOTO n
  2047                          
  2048                          					; is var or keyword
  2049                          LAB_174D
  2050  96fd c990               	CMP	#TK_RETURN		; compare the byte with the token for RETURN
  2051  96ff d003               	BNE	LAB_174G		; if it wasn't RETURN go interpret BASIC code from (Bpntrl)
  2052                          					; and return to this code to process any following code
  2053                          
  2054  9701 4c1595             	JMP	LAB_1602		; else it was RETURN so interpret BASIC code from (Bpntrl)
  2055                          					; but don't return here
  2056                          
  2057                          LAB_174G
  2058  9704 201395             	JSR	LAB_15FF		; interpret BASIC code from (Bpntrl)
  2059                          
  2060                          ; the IF was executed and there may be a following ELSE so the code needs to return
  2061                          ; here to check and ignore the ELSE if present
  2062                          
  2063  9707 a000               	LDY	#$00			; clear the index
  2064  9709 b1c3               	LDA	(Bpntrl),Y		; get the next BASIC byte
  2065  970b c9ae               	CMP	#TK_ELSE		; compare it with the token for ELSE
  2066  970d f099               	BEQ	LAB_DATA		; if ELSE ignore the following statement
  2067                          
  2068                          ; there was no ELSE so continue execution of IF <expr> THEN <stat> [: <stat>]. any
  2069                          ; following ELSE will, correctly, cause a syntax error
  2070                          
  2071  970f 60                 	RTS				; else return to the interpreter inner loop
  2072                          
  2073                          ; perform ELSE after IF
  2074                          
  2075                          LAB_174E
  2076  9710 a000               	LDY	#$00			; clear the BASIC byte index
  2077  9712 a201               	LDX	#$01			; clear the nesting depth
  2078                          LAB_1750
  2079  9714 c8                 	INY				; increment the BASIC byte index
  2080  9715 b1c3               	LDA	(Bpntrl),Y		; get the next BASIC byte
  2081  9717 f00f               	BEQ	LAB_1753		; if EOL go add the pointer and return
  2082                          
  2083  9719 c98b               	CMP	#TK_IF		; compare the byte with the token for IF
  2084  971b d003               	BNE	LAB_1752		; if not IF token skip the depth increment
  2085                          
  2086  971d e8                 	INX				; else increment the nesting depth ..
  2087  971e d0f4               	BNE	LAB_1750		; .. and continue looking
  2088                          
  2089                          LAB_1752
  2090  9720 c9ae               	CMP	#TK_ELSE		; compare the byte with the token for ELSE
  2091  9722 d0f0               	BNE	LAB_1750		; if not ELSE token continue looking
  2092                          
  2093  9724 ca                 	DEX				; was ELSE so decrement the nesting depth
  2094  9725 d0ed               	BNE	LAB_1750		; loop if still nested
  2095                          
  2096  9727 c8                 	INY				; increment the BASIC byte index past the ELSE
  2097                          
  2098                          ; found the matching ELSE, now do <{n|statement}>
  2099                          
  2100                          LAB_1753
  2101  9728 98                 	TYA				; else copy line index to A
  2102  9729 18                 	CLC				; clear carry for add
  2103  972a 65c3               	ADC	Bpntrl		; add the BASIC execute pointer low byte
  2104  972c 85c3               	STA	Bpntrl		; save the BASIC execute pointer low byte
  2105  972e 9002               	BCC	LAB_1754		; branch if no overflow to high byte
  2106                          
  2107  9730 e6c4               	INC	Bpntrh		; else increment the BASIC execute pointer high byte
  2108                          LAB_1754
  2109  9732 20c200             	JSR	LAB_GBYT		; scan memory
  2110  9735 90c3               	BCC	LAB_174C		; if numeric do GOTO n
  2111                          					; the code will return to the interpreter loop at the
  2112                          					; tail end of the GOTO <n>
  2113                          
  2114  9737 4c1395             	JMP	LAB_15FF		; interpret BASIC code from (Bpntrl)
  2115                          					; the code will return to the interpreter loop at the
  2116                          					; tail end of the <statement>
  2117                          
  2118                          ; perform REM, skip (rest of) line
  2119                          
  2120                          LAB_REM
  2121  973a 20bc96             	JSR	LAB_SNBL		; scan for next BASIC line
  2122  973d 4cab96             	JMP	LAB_170F		; go set BASIC execute pointer and return, branch always
  2123                          
  2124                          LAB_16FD
  2125  9740 4c199c             	JMP	LAB_SNER		; do syntax error then warm start
  2126                          
  2127                          ; perform ON
  2128                          
  2129                          LAB_ON
  2130  9743 c9ab               	CMP	#TK_IRQ		; was it IRQ token ?
  2131  9745 d003               	BNE	LAB_NOIN		; if not go check NMI
  2132                          
  2133  9747 4c4faf             	JMP	LAB_SIRQ		; else go set-up IRQ
  2134                          
  2135                          LAB_NOIN
  2136  974a c9ac               	CMP	#TK_NMI		; was it NMI token ?
  2137  974c d003               	BNE	LAB_NONM		; if not go do normal ON command
  2138                          
  2139  974e 4c53af             	JMP	LAB_SNMI		; else go set-up NMI
  2140                          
  2141                          LAB_NONM
  2142  9751 20a3a4             	JSR	LAB_GTBY		; get byte parameter
  2143  9754 48                 	PHA				; push GOTO/GOSUB token
  2144  9755 c98d               	CMP	#TK_GOSUB		; compare with GOSUB token
  2145  9757 f004               	BEQ	LAB_176B		; branch if GOSUB
  2146                          
  2147  9759 c989               	CMP	#TK_GOTO		; compare with GOTO token
  2148                          LAB_1767
  2149  975b d0e3               	BNE	LAB_16FD		; if not GOTO do syntax error then warm start
  2150                          
  2151                          
  2152                          ; next character was GOTO or GOSUB
  2153                          
  2154                          LAB_176B
  2155  975d c6af               	DEC	FAC1_3		; decrement index (byte value)
  2156  975f d004               	BNE	LAB_1773		; branch if not zero
  2157                          
  2158  9761 68                 	PLA				; pull GOTO/GOSUB token
  2159  9762 4c1595             	JMP	LAB_1602		; go execute it
  2160                          
  2161                          LAB_1773
  2162  9765 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  2163  9768 207197             	JSR	LAB_GFPN		; get fixed-point number into temp integer (skip this n)
  2164                          					; (we could LDX #',' and JSR LAB_SNBL+2, then we
  2165                          					; just BNE LAB_176B for the loop. should be quicker ..
  2166                          					; no we can't, what if we meet a colon or [EOL]?)
  2167  976b c92c               	CMP	#$2C			; compare next character with ","
  2168  976d f0ee               	BEQ	LAB_176B		; loop if ","
  2169                          
  2170                          LAB_177E
  2171  976f 68                 	PLA				; else pull keyword token (run out of options)
  2172                          					; also dump +/-1 pointer low byte and exit
  2173                          LAB_177F
  2174  9770 60                 	RTS
  2175                          
  2176                          ; takes n * 106 + 11 cycles where n is the number of digits
  2177                          
  2178                          ; get fixed-point number into temp integer
  2179                          
  2180                          LAB_GFPN
  2181  9771 a200               	LDX	#$00			; clear reg
  2182  9773 8611               	STX	Itempl		; clear temporary integer low byte
  2183                          LAB_1785
  2184  9775 8612               	STX	Itemph		; save temporary integer high byte
  2185  9777 b0f7               	BCS	LAB_177F		; return if carry set, end of scan, character was
  2186                          					; not 0-9
  2187                          
  2188  9779 e019               	CPX	#$19			; compare high byte with $19
  2189  977b a8                 	TAY				; ensure Zb = 0 if the branch is taken
  2190  977c b0dd               	BCS	LAB_1767		; branch if >=, makes max line # 63999 because next
  2191                          					; bit does *$0A, = 64000, compare at target will fail
  2192                          					; and do syntax error
  2193                          
  2194  977e e92f               	SBC	#'0'-1		; subtract "0", $2F + carry, from byte
  2195  9780 a8                 	TAY				; copy binary digit
  2196  9781 a511               	LDA	Itempl		; get temporary integer low byte
  2197  9783 0a                 	ASL				; *2 low byte
  2198  9784 2612               	ROL	Itemph		; *2 high byte
  2199  9786 0a                 	ASL				; *2 low byte
  2200  9787 2612               	ROL	Itemph		; *2 high byte, *4
  2201  9789 6511               	ADC	Itempl		; + low byte, *5
  2202  978b 8511               	STA	Itempl		; save it
  2203  978d 8a                 	TXA				; get high byte copy to A
  2204  978e 6512               	ADC	Itemph		; + high byte, *5
  2205  9790 0611               	ASL	Itempl		; *2 low byte, *10d
  2206  9792 2a                 	ROL				; *2 high byte, *10d
  2207  9793 aa                 	TAX				; copy high byte back to X
  2208  9794 98                 	TYA				; get binary digit back
  2209  9795 6511               	ADC	Itempl		; add number low byte
  2210  9797 8511               	STA	Itempl		; save number low byte
  2211  9799 9001               	BCC	LAB_17B3		; if no overflow to high byte get next character
  2212                          
  2213  979b e8                 	INX				; else increment high byte
  2214                          LAB_17B3
  2215  979c 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  2216  979f 4c7597             	JMP	LAB_1785		; loop for next character
  2217                          
  2218                          ; perform DEC
  2219                          
  2220                          LAB_DEC
  2221  97a2 a910               	LDA	#<LAB_2AFD		; set -1 pointer low byte
  2222  97a4 2c                 	!text	$2C			; BIT abs to skip the LDA below
  2223                          
  2224                          ; perform INC
  2225                          
  2226                          LAB_INC
  2227  97a5 a90c               	LDA	#<LAB_259C		; set 1 pointer low byte
  2228                          LAB_17B5
  2229  97a7 48                 	PHA				; save +/-1 pointer low byte
  2230                          LAB_17B7
  2231  97a8 20c19d             	JSR	LAB_GVAR		; get var address
  2232  97ab a65f               	LDX	Dtypef		; get data type flag, $FF=string, $00=numeric
  2233  97ad 301e               	BMI	IncrErr		; exit if string
  2234                          
  2235  97af 8597               	STA	Lvarpl		; save var address low byte
  2236  97b1 8498               	STY	Lvarph		; save var address high byte
  2237  97b3 2094a8             	JSR	LAB_UFAC		; unpack memory (AY) into FAC1
  2238  97b6 68                 	PLA				; get +/-1 pointer low byte
  2239  97b7 48                 	PHA				; save +/-1 pointer low byte
  2240  97b8 a0b2               	LDY	#>LAB_259C		; set +/-1 pointer high byte (both the same)
  2241  97ba 20d5a5             	JSR	LAB_246C		; add (AY) to FAC1
  2242  97bd 20baa8             	JSR	LAB_PFAC		; pack FAC1 into variable (Lvarpl)
  2243                          
  2244  97c0 20c200             	JSR	LAB_GBYT		; scan memory
  2245  97c3 c92c               	CMP	#','			; compare with ","
  2246  97c5 d0a8               	BNE	LAB_177E		; exit if not "," (either end or error)
  2247                          
  2248                          					; was "," so another INCR variable to do
  2249  97c7 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  2250  97ca 4ca897             	JMP	LAB_17B7		; go do next var
  2251                          
  2252                          IncrErr
  2253  97cd 4cf39a             	JMP	LAB_1ABC		; do "Type mismatch" error then warm start
  2254                          
  2255                          ; perform LET
  2256                          
  2257                          LAB_LET
  2258  97d0 20c19d             	JSR	LAB_GVAR		; get var address
  2259  97d3 8597               	STA	Lvarpl		; save var address low byte
  2260  97d5 8498               	STY	Lvarph		; save var address high byte
  2261  97d7 a9c3               	LDA	#TK_EQUAL		; get = token
  2262  97d9 20089c             	JSR	LAB_SCCA		; scan for CHR$(A), else do syntax error then warm start
  2263  97dc a55f               	LDA	Dtypef		; get data type flag, $FF=string, $00=numeric
  2264  97de 48                 	PHA				; push data type flag
  2265  97df 20f89a             	JSR	LAB_EVEX		; evaluate expression
  2266  97e2 68                 	PLA				; pop data type flag
  2267  97e3 2a                 	ROL				; set carry if type = string
  2268  97e4 20ea9a             	JSR	LAB_CKTM		; type match check, set C for string
  2269  97e7 d003               	BNE	LAB_17D5		; branch if string
  2270                          
  2271  97e9 4cbaa8             	JMP	LAB_PFAC		; pack FAC1 into variable (Lvarpl) and return
  2272                          
  2273                          ; string LET
  2274                          
  2275                          LAB_17D5
  2276  97ec a002               	LDY	#$02			; set index to pointer high byte
  2277  97ee b1ae               	LDA	(des_pl),Y		; get string pointer high byte
  2278  97f0 c582               	CMP	Sstorh		; compare bottom of string space high byte
  2279  97f2 9017               	BCC	LAB_17F4		; if less assign value and exit (was in program memory)
  2280                          
  2281  97f4 d007               	BNE	LAB_17E6		; branch if >
  2282                          					; else was equal so compare low bytes
  2283  97f6 88                 	DEY				; decrement index
  2284  97f7 b1ae               	LDA	(des_pl),Y		; get pointer low byte
  2285  97f9 c581               	CMP	Sstorl		; compare bottom of string space low byte
  2286  97fb 900e               	BCC	LAB_17F4		; if less assign value and exit (was in program memory)
  2287                          
  2288                          					; pointer was >= to bottom of string space pointer
  2289                          LAB_17E6
  2290  97fd a4af               	LDY	des_ph		; get descriptor pointer high byte
  2291  97ff c47c               	CPY	Svarh			; compare start of vars high byte
  2292  9801 9008               	BCC	LAB_17F4		; branch if less (descriptor is on stack)
  2293                          
  2294  9803 d00d               	BNE	LAB_17FB		; branch if greater (descriptor is not on stack)
  2295                          
  2296                          					; else high bytes were equal so ..
  2297  9805 a5ae               	LDA	des_pl		; get descriptor pointer low byte
  2298  9807 c57b               	CMP	Svarl			; compare start of vars low byte
  2299  9809 b007               	BCS	LAB_17FB		; branch if >= (descriptor is not on stack)
  2300                          
  2301                          LAB_17F4
  2302  980b a5ae               	LDA	des_pl		; get descriptor pointer low byte
  2303  980d a4af               	LDY	des_ph		; get descriptor pointer high byte
  2304  980f 4c2898             	JMP	LAB_1811		; clean stack, copy descriptor to variable and return
  2305                          
  2306                          					; make space and copy string
  2307                          LAB_17FB
  2308  9812 a000               	LDY	#$00			; index to length
  2309  9814 b1ae               	LDA	(des_pl),Y		; get string length
  2310  9816 2049a1             	JSR	LAB_209C		; copy string
  2311  9819 a59e               	LDA	des_2l		; get descriptor pointer low byte
  2312  981b a49f               	LDY	des_2h		; get descriptor pointer high byte
  2313  981d 85b8               	STA	ssptr_l		; save descriptor pointer low byte
  2314  981f 84b9               	STY	ssptr_h		; save descriptor pointer high byte
  2315  9821 2028a3             	JSR	LAB_228A		; copy string from descriptor (sdescr) to (Sutill)
  2316  9824 a9ac               	LDA	#<FAC1_e		; set descriptor pointer low byte
  2317  9826 a000               	LDY	#>FAC1_e		; get descriptor pointer high byte
  2318                          
  2319                          					; clean stack and assign value to string variable
  2320                          LAB_1811
  2321  9828 859e               	STA	des_2l		; save descriptor_2 pointer low byte
  2322  982a 849f               	STY	des_2h		; save descriptor_2 pointer high byte
  2323  982c 208aa3             	JSR	LAB_22EB		; clean descriptor stack, YA = pointer
  2324  982f a000               	LDY	#$00			; index to length
  2325  9831 b19e               	LDA	(des_2l),Y		; get string length
  2326  9833 9197               	STA	(Lvarpl),Y		; copy to let string variable
  2327  9835 c8                 	INY				; index to string pointer low byte
  2328  9836 b19e               	LDA	(des_2l),Y		; get string pointer low byte
  2329  9838 9197               	STA	(Lvarpl),Y		; copy to let string variable
  2330  983a c8                 	INY				; index to string pointer high byte
  2331  983b b19e               	LDA	(des_2l),Y		; get string pointer high byte
  2332  983d 9197               	STA	(Lvarpl),Y		; copy to let string variable
  2333  983f 60                 	RTS
  2334                          
  2335                          ; perform GET
  2336                          
  2337                          LAB_GET
  2338  9840 20c19d             	JSR	LAB_GVAR		; get var address
  2339  9843 8597               	STA	Lvarpl		; save var address low byte
  2340  9845 8498               	STY	Lvarph		; save var address high byte
  2341  9847 2017af             	JSR	INGET			; get input byte
  2342  984a a65f               	LDX	Dtypef		; get data type flag, $FF=string, $00=numeric
  2343  984c 3007               	BMI	LAB_GETS		; go get string character
  2344                          
  2345                          					; was numeric get
  2346  984e a8                 	TAY				; copy character to Y
  2347  984f 207da0             	JSR	LAB_1FD0		; convert Y to byte in FAC1
  2348  9852 4cbaa8             	JMP	LAB_PFAC		; pack FAC1 into variable (Lvarpl) and return
  2349                          
  2350                          LAB_GETS
  2351  9855 48                 	PHA				; save character
  2352  9856 a901               	LDA	#$01			; string is single byte
  2353  9858 b001               	BCS	LAB_IsByte		; branch if byte received
  2354                          
  2355  985a 68                 	PLA				; string is null
  2356                          LAB_IsByte
  2357  985b 2051a1             	JSR	LAB_MSSP		; make string space A bytes long A=$AC=length,
  2358                          					; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte
  2359  985e f005               	BEQ	LAB_NoSt		; skip store if null string
  2360                          
  2361  9860 68                 	PLA				; get character back
  2362  9861 a000               	LDY	#$00			; clear index
  2363  9863 91ad               	STA	(str_pl),Y		; save byte in string (byte IS string!)
  2364                          LAB_NoSt
  2365  9865 209ca1             	JSR	LAB_RTST		; check for space on descriptor stack then put address
  2366                          					; and length on descriptor stack and update stack pointers
  2367                          
  2368  9868 4cec97             	JMP	LAB_17D5		; do string LET and return
  2369                          
  2370                          ; perform PRINT
  2371                          
  2372                          LAB_1829
  2373  986b 20ed98             	JSR	LAB_18C6		; print string from Sutill/Sutilh
  2374                          LAB_182C
  2375  986e 20c200             	JSR	LAB_GBYT		; scan memory
  2376                          
  2377                          ; PRINT
  2378                          
  2379                          LAB_PRINT
  2380  9871 f03b               	BEQ	LAB_CRLF		; if nothing following just print CR/LF
  2381                          
  2382                          LAB_1831
  2383  9873 c9ad               	CMP	#TK_TAB		; compare with TAB( token
  2384  9875 f051               	BEQ	LAB_18A2		; go do TAB/SPC
  2385                          
  2386  9877 c9b1               	CMP	#TK_SPC		; compare with SPC( token
  2387  9879 f04d               	BEQ	LAB_18A2		; go do TAB/SPC
  2388                          
  2389  987b c92c               	CMP	#','			; compare with ","
  2390  987d f033               	BEQ	LAB_188B		; go do move to next TAB mark
  2391                          
  2392  987f c93b               	CMP	#';'			; compare with ";"
  2393  9881 f061               	BEQ	LAB_18BD		; if ";" continue with PRINT processing
  2394                          
  2395  9883 20f89a             	JSR	LAB_EVEX		; evaluate expression
  2396  9886 245f               	BIT	Dtypef		; test data type flag, $FF=string, $00=numeric
  2397  9888 30e1               	BMI	LAB_1829		; branch if string
  2398                          
  2399  988a 20acaa             	JSR	LAB_296E		; convert FAC1 to string
  2400  988d 205ba1             	JSR	LAB_20AE		; print " terminated string to Sutill/Sutilh
  2401  9890 a000               	LDY	#$00			; clear index
  2402                          
  2403                          ; don't check fit if terminal width byte is zero
  2404                          
  2405  9892 a50f               	LDA	TWidth		; get terminal width byte
  2406  9894 f00a               	BEQ	LAB_185E		; skip check if zero
  2407                          
  2408  9896 38                 	SEC				; set carry for subtract
  2409  9897 e50e               	SBC	TPos			; subtract terminal position
  2410  9899 f1ae               	SBC	(des_pl),Y		; subtract string length
  2411  989b b003               	BCS	LAB_185E		; branch if less than terminal width
  2412                          
  2413  989d 20ae98             	JSR	LAB_CRLF		; else print CR/LF
  2414                          LAB_185E
  2415  98a0 20ed98             	JSR	LAB_18C6		; print string from Sutill/Sutilh
  2416  98a3 f0c9               	BEQ	LAB_182C		; always go continue processing line
  2417                          
  2418                          ; CR/LF return to BASIC from BASIC input handler
  2419                          
  2420                          LAB_1866
  2421  98a5 a900               	LDA	#$00			; clear byte
  2422  98a7 9d2103             	STA	Ibuffs,X		; null terminate input
  2423  98aa a221               	LDX	#<Ibuffs		; set X to buffer start-1 low byte
  2424  98ac a003               	LDY	#>Ibuffs		; set Y to buffer start-1 high byte
  2425                          
  2426                          ; print CR/LF
  2427                          
  2428                          LAB_CRLF
  2429                          	;LDA	#$0D			; load [CR]
  2430                          	;JSR	LAB_PRNA		; go print the character
  2431  98ae a90a               	LDA	#$0A			; load [LF]
  2432  98b0 d052               	BNE	LAB_PRNA		; go print the character and return, branch always
  2433                          
  2434                          LAB_188B
  2435  98b2 a50e               	LDA	TPos			; get terminal position
  2436  98b4 c510               	CMP	Iclim			; compare with input column limit
  2437  98b6 9005               	BCC	LAB_1897		; branch if less
  2438                          
  2439  98b8 20ae98             	JSR	LAB_CRLF		; else print CR/LF (next line)
  2440  98bb d027               	BNE	LAB_18BD		; continue with PRINT processing (branch always)
  2441                          
  2442                          LAB_1897
  2443  98bd 38                 	SEC				; set carry for subtract
  2444                          LAB_1898
  2445  98be e564               	SBC	TabSiz		; subtract TAB size
  2446  98c0 b0fc               	BCS	LAB_1898		; loop if result was +ve
  2447                          
  2448  98c2 49ff               	EOR	#$FF			; complement it
  2449  98c4 6901               	ADC	#$01			; +1 (twos complement)
  2450  98c6 d012               	BNE	LAB_18B6		; always print A spaces (result is never $00)
  2451                          
  2452                          					; do TAB/SPC
  2453                          LAB_18A2
  2454  98c8 48                 	PHA				; save token
  2455  98c9 20a0a4             	JSR	LAB_SGBY		; scan and get byte parameter
  2456  98cc c929               	CMP	#$29			; is next character )
  2457  98ce d07b               	BNE	LAB_1910		; if not do syntax error then warm start
  2458                          
  2459  98d0 68                 	PLA				; get token back
  2460  98d1 c9ad               	CMP	#TK_TAB		; was it TAB ?
  2461  98d3 d006               	BNE	LAB_18B7		; if not go do SPC
  2462                          
  2463                          					; calculate TAB offset
  2464  98d5 8a                 	TXA				; copy integer value to A
  2465  98d6 e50e               	SBC	TPos			; subtract terminal position
  2466  98d8 900a               	BCC	LAB_18BD		; branch if result was < 0 (can't TAB backwards)
  2467                          
  2468                          					; print A spaces
  2469                          LAB_18B6
  2470  98da aa                 	TAX				; copy result to X
  2471                          LAB_18B7
  2472  98db 8a                 	TXA				; set flags on size for SPC
  2473  98dc f006               	BEQ	LAB_18BD		; branch if result was = $0, already here
  2474                          
  2475                          					; print X spaces
  2476                          LAB_18BA
  2477  98de 20ff98             	JSR	LAB_18E0		; print " "
  2478  98e1 ca                 	DEX				; decrement count
  2479  98e2 d0fa               	BNE	LAB_18BA		; loop if not all done
  2480                          
  2481                          					; continue with PRINT processing
  2482                          LAB_18BD
  2483  98e4 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  2484  98e7 d08a               	BNE	LAB_1831		; if more to print go do it
  2485                          
  2486  98e9 60                 	RTS
  2487                          
  2488                          ; print null terminated string from memory
  2489                          
  2490                          LAB_18C3
  2491  98ea 205ba1             	JSR	LAB_20AE		; print " terminated string to Sutill/Sutilh
  2492                          
  2493                          ; print string from Sutill/Sutilh
  2494                          
  2495                          LAB_18C6
  2496  98ed 2055a3             	JSR	LAB_22B6		; pop string off descriptor stack, or from top of string
  2497                          					; space returns with A = length, X=$71=pointer low byte,
  2498                          					; Y=$72=pointer high byte
  2499  98f0 a000               	LDY	#$00			; reset index
  2500  98f2 aa                 	TAX				; copy length to X
  2501  98f3 f049               	BEQ	LAB_188C		; exit (RTS) if null string
  2502                          
  2503                          LAB_18CD
  2504                          
  2505  98f5 b171               	LDA	(ut1_pl),Y		; get next byte
  2506  98f7 200499             	JSR	LAB_PRNA		; go print the character
  2507  98fa c8                 	INY				; increment index
  2508  98fb ca                 	DEX				; decrement count
  2509  98fc d0f7               	BNE	LAB_18CD		; loop if not done yet
  2510                          
  2511  98fe 60                 	RTS
  2512                          
  2513                          					; Print single format character
  2514                          ; print " "
  2515                          
  2516                          LAB_18E0
  2517  98ff a920               	LDA	#$20			; load " "
  2518  9901 2c                 	!text	$2C			; change next line to BIT LAB_3FA9
  2519                          
  2520                          ; print "?" character
  2521                          
  2522                          LAB_18E3
  2523  9902 a93f               	LDA	#$3F			; load "?" character
  2524                          
  2525                          ; print character in A
  2526                          ; now includes the null handler
  2527                          ; also includes infinite line length code
  2528                          ; note! some routines expect this one to exit with Zb=0
  2529                          
  2530                          LAB_PRNA
  2531  9904 c920               	CMP	#' '			; compare with " "
  2532  9906 9019               	BCC	LAB_18F9		; branch if less (non printing)
  2533                          
  2534                          					; else printable character
  2535  9908 48                 	PHA				; save the character
  2536                          
  2537                          ; don't check fit if terminal width byte is zero
  2538                          
  2539  9909 a50f               	LDA	TWidth		; get terminal width
  2540  990b d00a               	BNE	LAB_18F0		; branch if not zero (not infinite length)
  2541                          
  2542                          ; is "infinite line" so check TAB position
  2543                          
  2544  990d a50e               	LDA	TPos			; get position
  2545  990f e564               	SBC	TabSiz		; subtract TAB size, carry set by CMP #$20 above
  2546  9911 d00b               	BNE	LAB_18F7		; skip reset if different
  2547                          
  2548  9913 850e               	STA	TPos			; else reset position
  2549  9915 f007               	BEQ	LAB_18F7		; go print character
  2550                          
  2551                          LAB_18F0
  2552  9917 c50e               	CMP	TPos			; compare with terminal character position
  2553  9919 d003               	BNE	LAB_18F7		; branch if not at end of line
  2554                          
  2555  991b 20ae98             	JSR	LAB_CRLF		; else print CR/LF
  2556                          LAB_18F7
  2557  991e e60e               	INC	TPos			; increment terminal position
  2558  9920 68                 	PLA				; get character back
  2559                          LAB_18F9
  2560  9921 2019b1             	JSR	V_OUTP		; output byte via output vector
  2561  9924 c90d               	CMP	#$0D			; compare with [CR]
  2562  9926 d014               	BNE	LAB_188A		; branch if not [CR]
  2563                          
  2564                          					; else print nullct nulls after the [CR]
  2565  9928 8678               	STX	TempB			; save buffer index
  2566  992a a60d               	LDX	Nullct		; get null count
  2567  992c f00a               	BEQ	LAB_1886		; branch if no nulls
  2568                          
  2569  992e a900               	LDA	#$00			; load [NULL]
  2570                          LAB_1880
  2571  9930 200499             	JSR	LAB_PRNA		; go print the character
  2572  9933 ca                 	DEX				; decrement count
  2573  9934 d0fa               	BNE	LAB_1880		; loop if not all done
  2574                          
  2575  9936 a90d               	LDA	#$0D			; restore the character (and set the flags)
  2576                          LAB_1886
  2577  9938 860e               	STX	TPos			; clear terminal position (X always = zero when we get here)
  2578  993a a678               	LDX	TempB			; restore buffer index
  2579                          LAB_188A
  2580  993c 29ff               	AND	#$FF			; set the flags
  2581                          LAB_188C
  2582  993e 60                 	RTS
  2583                          
  2584                          ; handle bad input data
  2585                          
  2586                          LAB_1904
  2587  993f a562               	LDA	Imode			; get input mode flag, $00=INPUT, $00=READ
  2588  9941 100b               	BPL	LAB_1913		; branch if INPUT (go do redo)
  2589                          
  2590  9943 a58d               	LDA	Dlinel		; get current DATA line low byte
  2591  9945 a48e               	LDY	Dlineh		; get current DATA line high byte
  2592  9947 8587               	STA	Clinel		; save current line low byte
  2593  9949 8488               	STY	Clineh		; save current line high byte
  2594                          LAB_1910
  2595  994b 4c199c             	JMP	LAB_SNER		; do syntax error then warm start
  2596                          
  2597                          					; mode was INPUT
  2598                          LAB_1913
  2599  994e a968               	LDA	#<LAB_REDO		; point to redo message (low addr)
  2600  9950 a0b8               	LDY	#>LAB_REDO		; point to redo message (high addr)
  2601  9952 20ea98             	JSR	LAB_18C3		; print null terminated string from memory
  2602  9955 a58b               	LDA	Cpntrl		; get continue pointer low byte
  2603  9957 a48c               	LDY	Cpntrh		; get continue pointer high byte
  2604  9959 85c3               	STA	Bpntrl		; save BASIC execute pointer low byte
  2605  995b 84c4               	STY	Bpntrh		; save BASIC execute pointer high byte
  2606  995d 60                 	RTS
  2607                          
  2608                          ; perform INPUT
  2609                          
  2610                          LAB_INPUT
  2611  995e c922               	CMP	#$22			; compare next byte with open quote
  2612  9960 d00b               	BNE	LAB_1934		; branch if no prompt string
  2613                          
  2614  9962 20d59b             	JSR	LAB_1BC1		; print "..." string
  2615  9965 a93b               	LDA	#$3B			; load A with ";"
  2616  9967 20089c             	JSR	LAB_SCCA		; scan for CHR$(A), else do syntax error then warm start
  2617  996a 20ed98             	JSR	LAB_18C6		; print string from Sutill/Sutilh
  2618                          
  2619                          					; done with prompt, now get data
  2620                          LAB_1934
  2621  996d 2081a0             	JSR	LAB_CKRN		; check not Direct, back here if ok
  2622  9970 204b92             	JSR	LAB_INLN		; print "? " and get BASIC input
  2623  9973 a900               	LDA	#$00			; set mode = INPUT
  2624  9975 cd2103             	CMP	Ibuffs		; test first byte in buffer
  2625  9978 d00a               	BNE	LAB_1953		; branch if not null input
  2626                          
  2627  997a 18                 	CLC				; was null input so clear carry to exit program
  2628  997b 4c4395             	JMP	LAB_1647		; go do BREAK exit
  2629                          
  2630                          ; perform READ
  2631                          
  2632                          LAB_READ
  2633  997e a68f               	LDX	Dptrl			; get DATA pointer low byte
  2634  9980 a490               	LDY	Dptrh			; get DATA pointer high byte
  2635  9982 a980               	LDA	#$80			; set mode = READ
  2636                          
  2637                          LAB_1953
  2638  9984 8562               	STA	Imode			; set input mode flag, $00=INPUT, $80=READ
  2639  9986 8691               	STX	Rdptrl		; save READ pointer low byte
  2640  9988 8492               	STY	Rdptrh		; save READ pointer high byte
  2641                          
  2642                          					; READ or INPUT next variable from list
  2643                          LAB_195B
  2644  998a 20c19d             	JSR	LAB_GVAR		; get (var) address
  2645  998d 8597               	STA	Lvarpl		; save address low byte
  2646  998f 8498               	STY	Lvarph		; save address high byte
  2647  9991 a5c3               	LDA	Bpntrl		; get BASIC execute pointer low byte
  2648  9993 a4c4               	LDY	Bpntrh		; get BASIC execute pointer high byte
  2649  9995 8511               	STA	Itempl		; save as temporary integer low byte
  2650  9997 8412               	STY	Itemph		; save as temporary integer high byte
  2651  9999 a691               	LDX	Rdptrl		; get READ pointer low byte
  2652  999b a492               	LDY	Rdptrh		; get READ pointer high byte
  2653  999d 86c3               	STX	Bpntrl		; set BASIC execute pointer low byte
  2654  999f 84c4               	STY	Bpntrh		; set BASIC execute pointer high byte
  2655  99a1 20c200             	JSR	LAB_GBYT		; scan memory
  2656  99a4 d011               	BNE	LAB_1988		; branch if not null
  2657                          
  2658                          					; pointer was to null entry
  2659  99a6 2462               	BIT	Imode			; test input mode flag, $00=INPUT, $80=READ
  2660  99a8 3065               	BMI	LAB_19DD		; branch if READ
  2661                          
  2662                          					; mode was INPUT
  2663  99aa 200299             	JSR	LAB_18E3		; print "?" character (double ? for extended input)
  2664  99ad 204b92             	JSR	LAB_INLN		; print "? " and get BASIC input
  2665  99b0 86c3               	STX	Bpntrl		; set BASIC execute pointer low byte
  2666  99b2 84c4               	STY	Bpntrh		; set BASIC execute pointer high byte
  2667                          LAB_1985
  2668  99b4 20c200             	JSR	LAB_GBYT		; scan memory
  2669                          LAB_1988
  2670  99b7 245f               	BIT	Dtypef		; test data type flag, $FF=string, $00=numeric
  2671  99b9 1024               	BPL	LAB_19B0		; branch if numeric
  2672                          
  2673                          					; else get string
  2674  99bb 855b               	STA	Srchc			; save search character
  2675  99bd c922               	CMP	#$22			; was it " ?
  2676  99bf f007               	BEQ	LAB_1999		; branch if so
  2677                          
  2678  99c1 a93a               	LDA	#':'			; else search character is ":"
  2679  99c3 855b               	STA	Srchc			; set new search character
  2680  99c5 a92c               	LDA	#','			; other search character is ","
  2681  99c7 18                 	CLC				; clear carry for add
  2682                          LAB_1999
  2683  99c8 855c               	STA	Asrch			; set second search character
  2684  99ca a5c3               	LDA	Bpntrl		; get BASIC execute pointer low byte
  2685  99cc a4c4               	LDY	Bpntrh		; get BASIC execute pointer high byte
  2686                          
  2687  99ce 6900               	ADC	#$00			; c is =1 if we came via the BEQ LAB_1999, else =0
  2688  99d0 9001               	BCC	LAB_19A4		; branch if no execute pointer low byte rollover
  2689                          
  2690  99d2 c8                 	INY				; else increment high byte
  2691                          LAB_19A4
  2692  99d3 2061a1             	JSR	LAB_20B4		; print Srchc or Asrch terminated string to Sutill/Sutilh
  2693  99d6 20e6a4             	JSR	LAB_23F3		; restore BASIC execute pointer from temp (Btmpl/Btmph)
  2694  99d9 20ec97             	JSR	LAB_17D5		; go do string LET
  2695  99dc 4ce599             	JMP	LAB_19B6		; go check string terminator
  2696                          
  2697                          					; get numeric INPUT
  2698                          LAB_19B0
  2699  99df 20bda9             	JSR	LAB_2887		; get FAC1 from string
  2700  99e2 20baa8             	JSR	LAB_PFAC		; pack FAC1 into (Lvarpl)
  2701                          LAB_19B6
  2702  99e5 20c200             	JSR	LAB_GBYT		; scan memory
  2703  99e8 f00a               	BEQ	LAB_19C5		; branch if null (last entry)
  2704                          
  2705  99ea c92c               	CMP	#','			; else compare with ","
  2706  99ec f003               	BEQ	LAB_19C2		; branch if ","
  2707                          
  2708  99ee 4c3f99             	JMP	LAB_1904		; else go handle bad input data
  2709                          
  2710                          					; got good input data
  2711                          LAB_19C2
  2712  99f1 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  2713                          LAB_19C5
  2714  99f4 a5c3               	LDA	Bpntrl		; get BASIC execute pointer low byte (temp READ/INPUT ptr)
  2715  99f6 a4c4               	LDY	Bpntrh		; get BASIC execute pointer high byte (temp READ/INPUT ptr)
  2716  99f8 8591               	STA	Rdptrl		; save for now
  2717  99fa 8492               	STY	Rdptrh		; save for now
  2718  99fc a511               	LDA	Itempl		; get temporary integer low byte (temp BASIC execute ptr)
  2719  99fe a412               	LDY	Itemph		; get temporary integer high byte (temp BASIC execute ptr)
  2720  9a00 85c3               	STA	Bpntrl		; set BASIC execute pointer low byte
  2721  9a02 84c4               	STY	Bpntrh		; set BASIC execute pointer high byte
  2722  9a04 20c200             	JSR	LAB_GBYT		; scan memory
  2723  9a07 f02c               	BEQ	LAB_1A03		; if null go do extra ignored message
  2724                          
  2725  9a09 20159c             	JSR	LAB_1C01		; else scan for "," , else do syntax error then warm start
  2726  9a0c 4c8a99             	JMP	LAB_195B		; go INPUT next variable from list
  2727                          
  2728                          					; find next DATA statement or do "Out of DATA" error
  2729                          LAB_19DD
  2730  9a0f 20b996             	JSR	LAB_SNBS		; scan for next BASIC statement ([:] or [EOL])
  2731  9a12 c8                 	INY				; increment index
  2732  9a13 aa                 	TAX				; copy character ([:] or [EOL])
  2733  9a14 d012               	BNE	LAB_19F6		; branch if [:]
  2734                          
  2735  9a16 a206               	LDX	#$06			; set for "Out of DATA" error
  2736  9a18 c8                 	INY				; increment index, now points to next line pointer high byte
  2737  9a19 b1c3               	LDA	(Bpntrl),Y		; get next line pointer high byte
  2738  9a1b f073               	BEQ	LAB_1A54		; branch if end (eventually does error X)
  2739                          
  2740  9a1d c8                 	INY				; increment index
  2741  9a1e b1c3               	LDA	(Bpntrl),Y		; get next line # low byte
  2742  9a20 858d               	STA	Dlinel		; save current DATA line low byte
  2743  9a22 c8                 	INY				; increment index
  2744  9a23 b1c3               	LDA	(Bpntrl),Y		; get next line # high byte
  2745  9a25 c8                 	INY				; increment index
  2746  9a26 858e               	STA	Dlineh		; save current DATA line high byte
  2747                          LAB_19F6
  2748  9a28 b1c3               	LDA	(Bpntrl),Y		; get byte
  2749  9a2a c8                 	INY				; increment index
  2750  9a2b aa                 	TAX				; copy to X
  2751  9a2c 20ab96             	JSR	LAB_170F		; set BASIC execute pointer
  2752  9a2f e083               	CPX	#TK_DATA		; compare with "DATA" token
  2753  9a31 f081               	BEQ	LAB_1985		; was "DATA" so go do next READ
  2754                          
  2755  9a33 d0da               	BNE	LAB_19DD		; go find next statement if not "DATA"
  2756                          
  2757                          ; end of INPUT/READ routine
  2758                          
  2759                          LAB_1A03
  2760  9a35 a591               	LDA	Rdptrl		; get temp READ pointer low byte
  2761  9a37 a492               	LDY	Rdptrh		; get temp READ pointer high byte
  2762  9a39 a662               	LDX	Imode			; get input mode flag, $00=INPUT, $80=READ
  2763  9a3b 1003               	BPL	LAB_1A0E		; branch if INPUT
  2764                          
  2765  9a3d 4c6a95             	JMP	LAB_1624		; save AY as DATA pointer and return
  2766                          
  2767                          					; we were getting INPUT
  2768                          LAB_1A0E
  2769  9a40 a000               	LDY	#$00			; clear index
  2770  9a42 b191               	LDA	(Rdptrl),Y		; get next byte
  2771  9a44 d001               	BNE	LAB_1A1B		; error if not end of INPUT
  2772                          
  2773  9a46 60                 	RTS
  2774                          
  2775                          					; user typed too much
  2776                          LAB_1A1B
  2777  9a47 a957               	LDA	#<LAB_IMSG		; point to extra ignored message (low addr)
  2778  9a49 a0b8               	LDY	#>LAB_IMSG		; point to extra ignored message (high addr)
  2779  9a4b 4cea98             	JMP	LAB_18C3		; print null terminated string from memory and return
  2780                          
  2781                          ; search the stack for FOR activity
  2782                          ; exit with z=1 if FOR else exit with z=0
  2783                          
  2784                          LAB_11A1
  2785  9a4e ba                 	TSX				; copy stack pointer
  2786  9a4f e8                 	INX				; +1 pass return address
  2787  9a50 e8                 	INX				; +2 pass return address
  2788  9a51 e8                 	INX				; +3 pass calling routine return address
  2789  9a52 e8                 	INX				; +4 pass calling routine return address
  2790                          LAB_11A6
  2791  9a53 bd0101             	LDA	LAB_STAK+1,X	; get token byte from stack
  2792  9a56 c981               	CMP	#TK_FOR		; is it FOR token
  2793  9a58 d021               	BNE	LAB_11CE		; exit if not FOR token
  2794                          
  2795                          					; was FOR token
  2796  9a5a a598               	LDA	Frnxth		; get var pointer for FOR/NEXT high byte
  2797  9a5c d00a               	BNE	LAB_11BB		; branch if not null
  2798                          
  2799  9a5e bd0201             	LDA	LAB_STAK+2,X	; get FOR variable pointer low byte
  2800  9a61 8597               	STA	Frnxtl		; save var pointer for FOR/NEXT low byte
  2801  9a63 bd0301             	LDA	LAB_STAK+3,X	; get FOR variable pointer high byte
  2802  9a66 8598               	STA	Frnxth		; save var pointer for FOR/NEXT high byte
  2803                          LAB_11BB
  2804  9a68 dd0301             	CMP	LAB_STAK+3,X	; compare var pointer with stacked var pointer (high byte)
  2805  9a6b d007               	BNE	LAB_11C7		; branch if no match
  2806                          
  2807  9a6d a597               	LDA	Frnxtl		; get var pointer for FOR/NEXT low byte
  2808  9a6f dd0201             	CMP	LAB_STAK+2,X	; compare var pointer with stacked var pointer (low byte)
  2809  9a72 f007               	BEQ	LAB_11CE		; exit if match found
  2810                          
  2811                          LAB_11C7
  2812  9a74 8a                 	TXA				; copy index
  2813  9a75 18                 	CLC				; clear carry for add
  2814  9a76 6910               	ADC	#$10			; add FOR stack use size
  2815  9a78 aa                 	TAX				; copy back to index
  2816  9a79 d0d8               	BNE	LAB_11A6		; loop if not at start of stack
  2817                          
  2818                          LAB_11CE
  2819  9a7b 60                 	RTS
  2820                          
  2821                          ; perform NEXT
  2822                          
  2823                          LAB_NEXT
  2824  9a7c d004               	BNE	LAB_1A46		; branch if NEXT var
  2825                          
  2826  9a7e a000               	LDY	#$00			; else clear Y
  2827  9a80 f003               	BEQ	LAB_1A49		; branch always (no variable to search for)
  2828                          
  2829                          ; NEXT var
  2830                          
  2831                          LAB_1A46
  2832  9a82 20c19d             	JSR	LAB_GVAR		; get variable address
  2833                          LAB_1A49
  2834  9a85 8597               	STA	Frnxtl		; store variable pointer low byte
  2835  9a87 8498               	STY	Frnxth		; store variable pointer high byte
  2836                          					; (both cleared if no variable defined)
  2837  9a89 204e9a             	JSR	LAB_11A1		; search the stack for FOR activity
  2838  9a8c f004               	BEQ	LAB_1A56		; branch if found
  2839                          
  2840  9a8e a200               	LDX	#$00			; else set error $00 ("NEXT without FOR" error)
  2841                          LAB_1A54
  2842  9a90 f063               	BEQ	LAB_1ABE		; do error #X, then warm start
  2843                          
  2844                          LAB_1A56
  2845  9a92 9a                 	TXS				; set stack pointer, X set by search, dumps return addresses
  2846                          
  2847  9a93 8a                 	TXA				; copy stack pointer
  2848  9a94 38                 	SEC				; set carry for subtract
  2849  9a95 e9f7               	SBC	#$F7			; point to TO var
  2850  9a97 8573               	STA	ut2_pl		; save pointer to TO var for compare
  2851  9a99 69fb               	ADC	#$FB			; point to STEP var
  2852                          
  2853  9a9b a001               	LDY	#>LAB_STAK		; point to stack page high byte
  2854  9a9d 2094a8             	JSR	LAB_UFAC		; unpack memory (STEP value) into FAC1
  2855  9aa0 ba                 	TSX				; get stack pointer back
  2856  9aa1 bd0801             	LDA	LAB_STAK+8,X	; get step sign
  2857  9aa4 85b0               	STA	FAC1_s		; save FAC1 sign (b7)
  2858  9aa6 a597               	LDA	Frnxtl		; get FOR variable pointer low byte
  2859  9aa8 a498               	LDY	Frnxth		; get FOR variable pointer high byte
  2860  9aaa 20d5a5             	JSR	LAB_246C		; add (FOR variable) to FAC1
  2861  9aad 20baa8             	JSR	LAB_PFAC		; pack FAC1 into (FOR variable)
  2862  9ab0 a001               	LDY	#>LAB_STAK		; point to stack page high byte
  2863  9ab2 2030a9             	JSR	LAB_27FA		; compare FAC1 with (Y,ut2_pl) (TO value)
  2864  9ab5 ba                 	TSX				; get stack pointer back
  2865  9ab6 dd0801             	CMP	LAB_STAK+8,X	; compare step sign
  2866  9ab9 f017               	BEQ	LAB_1A9B		; branch if = (loop complete)
  2867                          
  2868                          					; loop back and do it all again
  2869  9abb bd0d01             	LDA	LAB_STAK+$0D,X	; get FOR line low byte
  2870  9abe 8587               	STA	Clinel		; save current line low byte
  2871  9ac0 bd0e01             	LDA	LAB_STAK+$0E,X	; get FOR line high byte
  2872  9ac3 8588               	STA	Clineh		; save current line high byte
  2873  9ac5 bd1001             	LDA	LAB_STAK+$10,X	; get BASIC execute pointer low byte
  2874  9ac8 85c3               	STA	Bpntrl		; save BASIC execute pointer low byte
  2875  9aca bd0f01             	LDA	LAB_STAK+$0F,X	; get BASIC execute pointer high byte
  2876  9acd 85c4               	STA	Bpntrh		; save BASIC execute pointer high byte
  2877                          LAB_1A98
  2878  9acf 4cd394             	JMP	LAB_15C2		; go do interpreter inner loop
  2879                          
  2880                          					; loop complete so carry on
  2881                          LAB_1A9B
  2882  9ad2 8a                 	TXA				; stack copy to A
  2883  9ad3 690f               	ADC	#$0F			; add $10 ($0F+carry) to dump FOR structure
  2884  9ad5 aa                 	TAX				; copy back to index
  2885  9ad6 9a                 	TXS				; copy to stack pointer
  2886  9ad7 20c200             	JSR	LAB_GBYT		; scan memory
  2887  9ada c92c               	CMP	#','			; compare with ","
  2888  9adc d0f1               	BNE	LAB_1A98		; branch if not "," (go do interpreter inner loop)
  2889                          
  2890                          					; was "," so another NEXT variable to do
  2891  9ade 20bc00             	JSR	LAB_IGBY		; else increment and scan memory
  2892  9ae1 20829a             	JSR	LAB_1A46		; do NEXT (var)
  2893                          
  2894                          ; evaluate expression and check is numeric, else do type mismatch
  2895                          
  2896                          LAB_EVNM
  2897  9ae4 20f89a             	JSR	LAB_EVEX		; evaluate expression
  2898                          
  2899                          ; check if source is numeric, else do type mismatch
  2900                          
  2901                          LAB_CTNM
  2902  9ae7 18                 	CLC				; destination is numeric
  2903  9ae8 24                 	!text	$24			; makes next line BIT $38
  2904                          
  2905                          ; check if source is string, else do type mismatch
  2906                          
  2907                          LAB_CTST
  2908  9ae9 38                 	SEC				; required type is string
  2909                          
  2910                          ; type match check, set C for string, clear C for numeric
  2911                          
  2912                          LAB_CKTM
  2913  9aea 245f               	BIT	Dtypef		; test data type flag, $FF=string, $00=numeric
  2914  9aec 3003               	BMI	LAB_1ABA		; branch if data type is string
  2915                          
  2916                          					; else data type was numeric
  2917  9aee b003               	BCS	LAB_1ABC		; if required type is string do type mismatch error
  2918                          LAB_1AB9
  2919  9af0 60                 	RTS
  2920                          
  2921                          					; data type was string, now check required type
  2922                          LAB_1ABA
  2923  9af1 b0fd               	BCS	LAB_1AB9		; exit if required type is string
  2924                          
  2925                          					; else do type mismatch error
  2926                          LAB_1ABC
  2927  9af3 a218               	LDX	#$18			; error code $18 ("Type mismatch" error)
  2928                          LAB_1ABE
  2929  9af5 4c4791             	JMP	LAB_XERR		; do error #X, then warm start
  2930                          
  2931                          ; evaluate expression
  2932                          
  2933                          LAB_EVEX
  2934  9af8 a6c3               	LDX	Bpntrl		; get BASIC execute pointer low byte
  2935  9afa d002               	BNE	LAB_1AC7		; skip next if not zero
  2936                          
  2937  9afc c6c4               	DEC	Bpntrh		; else decrement BASIC execute pointer high byte
  2938                          LAB_1AC7
  2939  9afe c6c3               	DEC	Bpntrl		; decrement BASIC execute pointer low byte
  2940                          
  2941                          LAB_EVEZ
  2942  9b00 a900               	LDA	#$00			; set null precedence (flag done)
  2943                          LAB_1ACC
  2944  9b02 48                 	PHA				; push precedence byte
  2945  9b03 a902               	LDA	#$02			; 2 bytes
  2946  9b05 200e91             	JSR	LAB_1212		; check room on stack for A bytes
  2947  9b08 20e49b             	JSR	LAB_GVAL		; get value from line
  2948  9b0b a900               	LDA	#$00			; clear A
  2949  9b0d 859b               	STA	comp_f		; clear compare function flag
  2950                          LAB_1ADB
  2951  9b0f 20c200             	JSR	LAB_GBYT		; scan memory
  2952                          LAB_1ADE
  2953  9b12 38                 	SEC				; set carry for subtract
  2954  9b13 e9c2               	SBC	#TK_GT		; subtract token for > (lowest comparison function)
  2955  9b15 9017               	BCC	LAB_1AFA		; branch if < TK_GT
  2956                          
  2957  9b17 c903               	CMP	#$03			; compare with ">" to "<" tokens
  2958  9b19 b013               	BCS	LAB_1AFA		; branch if >= TK_SGN (highest evaluation function +1)
  2959                          
  2960                          					; was token for > = or < (A = 0, 1 or 2)
  2961  9b1b c901               	CMP	#$01			; compare with token for =
  2962  9b1d 2a                 	ROL				; *2, b0 = carry (=1 if token was = or <)
  2963                          					; (A = 0, 3 or 5)
  2964  9b1e 4901               	EOR	#$01			; toggle b0
  2965                          					; (A = 1, 2 or 4. 1 if >, 2 if =, 4 if <)
  2966  9b20 459b               	EOR	comp_f		; EOR with compare function flag bits
  2967  9b22 c59b               	CMP	comp_f		; compare with compare function flag
  2968  9b24 9067               	BCC	LAB_1B53		; if <(comp_f) do syntax error then warm start
  2969                          					; was more than one <, = or >)
  2970                          
  2971  9b26 859b               	STA	comp_f		; save new compare function flag
  2972  9b28 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  2973  9b2b 4c129b             	JMP	LAB_1ADE		; go do next character
  2974                          
  2975                          					; token is < ">" or > "<" tokens
  2976                          LAB_1AFA
  2977  9b2e a69b               	LDX	comp_f		; get compare function flag
  2978  9b30 d02c               	BNE	LAB_1B2A		; branch if compare function
  2979                          
  2980  9b32 b079               	BCS	LAB_1B78		; go do functions
  2981                          
  2982                          					; else was <  TK_GT so is operator or lower
  2983  9b34 690a               	ADC	#TK_GT-TK_PLUS	; add # of operators (+, -, *, /, ^, AND, OR or EOR)
  2984  9b36 9075               	BCC	LAB_1B78		; branch if < + operator
  2985                          
  2986                          					; carry was set so token was +, -, *, /, ^, AND, OR or EOR
  2987  9b38 d007               	BNE	LAB_1B0B		; branch if not + token
  2988                          
  2989  9b3a 245f               	BIT	Dtypef		; test data type flag, $FF=string, $00=numeric
  2990  9b3c 1003               	BPL	LAB_1B0B		; branch if not string
  2991                          
  2992                          					; will only be $00 if type is string and token was +
  2993  9b3e 4ceba2             	JMP	LAB_224D		; add strings, string 1 is in descriptor des_pl, string 2
  2994                          					; is in line, and return
  2995                          
  2996                          LAB_1B0B
  2997  9b41 8571               	STA	ut1_pl		; save it
  2998  9b43 0a                 	ASL				; *2
  2999  9b44 6571               	ADC	ut1_pl		; *3
  3000  9b46 a8                 	TAY				; copy to index
  3001                          LAB_1B13
  3002  9b47 68                 	PLA				; pull previous precedence
  3003  9b48 d919b3             	CMP	LAB_OPPT,Y		; compare with precedence byte
  3004  9b4b b065               	BCS	LAB_1B7D		; branch if A >=
  3005                          
  3006  9b4d 20e79a             	JSR	LAB_CTNM		; check if source is numeric, else do type mismatch
  3007                          LAB_1B1C
  3008  9b50 48                 	PHA				; save precedence
  3009                          LAB_1B1D
  3010  9b51 20799b             	JSR	LAB_1B43		; get vector, execute function then continue evaluation
  3011  9b54 68                 	PLA				; restore precedence
  3012  9b55 a499               	LDY	prstk			; get precedence stacked flag
  3013  9b57 1019               	BPL	LAB_1B3C		; branch if stacked values
  3014                          
  3015  9b59 aa                 	TAX				; copy precedence (set flags)
  3016  9b5a f076               	BEQ	LAB_1B9D		; exit if done
  3017                          
  3018  9b5c d05d               	BNE	LAB_1B86		; else pop FAC2 and return, branch always
  3019                          
  3020                          LAB_1B2A
  3021  9b5e 265f               	ROL	Dtypef		; shift data type flag into Cb
  3022  9b60 8a                 	TXA				; copy compare function flag
  3023  9b61 855f               	STA	Dtypef		; clear data type flag, X is 0xxx xxxx
  3024  9b63 2a                 	ROL				; shift data type into compare function byte b0
  3025  9b64 a6c3               	LDX	Bpntrl		; get BASIC execute pointer low byte
  3026  9b66 d002               	BNE	LAB_1B34		; branch if no underflow
  3027                          
  3028  9b68 c6c4               	DEC	Bpntrh		; else decrement BASIC execute pointer high byte
  3029                          LAB_1B34
  3030  9b6a c6c3               	DEC	Bpntrl		; decrement BASIC execute pointer low byte
  3031                          TK_LT_PLUS	= TK_LT-TK_PLUS
  3032  9b6c a024               	LDY	#TK_LT_PLUS*3	; set offset to last operator entry
  3033  9b6e 859b               	STA	comp_f		; save new compare function flag
  3034  9b70 d0d5               	BNE	LAB_1B13		; branch always
  3035                          
  3036                          LAB_1B3C
  3037  9b72 d919b3             	CMP	LAB_OPPT,Y		;.compare with stacked function precedence
  3038  9b75 b044               	BCS	LAB_1B86		; branch if A >=, pop FAC2 and return
  3039                          
  3040  9b77 90d7               	BCC	LAB_1B1C		; branch always
  3041                          
  3042                          ;.get vector, execute function then continue evaluation
  3043                          
  3044                          LAB_1B43
  3045  9b79 b91bb3             	LDA	LAB_OPPT+2,Y	; get function vector high byte
  3046  9b7c 48                 	PHA				; onto stack
  3047  9b7d b91ab3             	LDA	LAB_OPPT+1,Y	; get function vector low byte
  3048  9b80 48                 	PHA				; onto stack
  3049                          					; now push sign, round FAC1 and put on stack
  3050  9b81 20909b             	JSR	LAB_1B5B		; function will return here, then the next RTS will call
  3051                          					; the function
  3052  9b84 a59b               	LDA	comp_f		; get compare function flag
  3053  9b86 48                 	PHA				; push compare evaluation byte
  3054  9b87 b919b3             	LDA	LAB_OPPT,Y		; get precedence byte
  3055  9b8a 4c029b             	JMP	LAB_1ACC		; continue evaluating expression
  3056                          
  3057                          LAB_1B53
  3058  9b8d 4c199c             	JMP	LAB_SNER		; do syntax error then warm start
  3059                          
  3060                          ; push sign, round FAC1 and put on stack
  3061                          
  3062                          LAB_1B5B
  3063  9b90 68                 	PLA				; get return addr low byte
  3064  9b91 8571               	STA	ut1_pl		; save it
  3065  9b93 e671               	INC	ut1_pl		; increment it (was ret-1 pushed? yes!)
  3066                          					; note! no check is made on the high byte! if the calling
  3067                          					; routine assembles to a page edge then this all goes
  3068                          					; horribly wrong !!!
  3069  9b95 68                 	PLA				; get return addr high byte
  3070  9b96 8572               	STA	ut1_ph		; save it
  3071  9b98 a5b0               	LDA	FAC1_s		; get FAC1 sign (b7)
  3072  9b9a 48                 	PHA				; push sign
  3073                          
  3074                          ; round FAC1 and put on stack
  3075                          
  3076                          LAB_1B66
  3077  9b9b 20f0a8             	JSR	LAB_27BA		; round FAC1
  3078  9b9e a5af               	LDA	FAC1_3		; get FAC1 mantissa3
  3079  9ba0 48                 	PHA				; push on stack
  3080  9ba1 a5ae               	LDA	FAC1_2		; get FAC1 mantissa2
  3081  9ba3 48                 	PHA				; push on stack
  3082  9ba4 a5ad               	LDA	FAC1_1		; get FAC1 mantissa1
  3083  9ba6 48                 	PHA				; push on stack
  3084  9ba7 a5ac               	LDA	FAC1_e		; get FAC1 exponent
  3085  9ba9 48                 	PHA				; push on stack
  3086  9baa 6c7100             	JMP	(ut1_pl)		; return, sort of
  3087                          
  3088                          ; do functions
  3089                          
  3090                          LAB_1B78
  3091  9bad a0ff               	LDY	#$FF			; flag function
  3092  9baf 68                 	PLA				; pull precedence byte
  3093                          LAB_1B7B
  3094  9bb0 f020               	BEQ	LAB_1B9D		; exit if done
  3095                          
  3096                          LAB_1B7D
  3097  9bb2 c964               	CMP	#$64			; compare previous precedence with $64
  3098  9bb4 f003               	BEQ	LAB_1B84		; branch if was $64 (< function)
  3099                          
  3100  9bb6 20e79a             	JSR	LAB_CTNM		; check if source is numeric, else do type mismatch
  3101                          LAB_1B84
  3102  9bb9 8499               	STY	prstk			; save precedence stacked flag
  3103                          
  3104                          					; pop FAC2 and return
  3105                          LAB_1B86
  3106  9bbb 68                 	PLA				; pop byte
  3107  9bbc 4a                 	LSR				; shift out comparison evaluation lowest bit
  3108  9bbd 8563               	STA	Cflag			; save comparison evaluation flag
  3109  9bbf 68                 	PLA				; pop exponent
  3110  9bc0 85b3               	STA	FAC2_e		; save FAC2 exponent
  3111  9bc2 68                 	PLA				; pop mantissa1
  3112  9bc3 85b4               	STA	FAC2_1		; save FAC2 mantissa1
  3113  9bc5 68                 	PLA				; pop mantissa2
  3114  9bc6 85b5               	STA	FAC2_2		; save FAC2 mantissa2
  3115  9bc8 68                 	PLA				; pop mantissa3
  3116  9bc9 85b6               	STA	FAC2_3		; save FAC2 mantissa3
  3117  9bcb 68                 	PLA				; pop sign
  3118  9bcc 85b7               	STA	FAC2_s		; save FAC2 sign (b7)
  3119  9bce 45b0               	EOR	FAC1_s		; EOR FAC1 sign (b7)
  3120  9bd0 85b8               	STA	FAC_sc		; save sign compare (FAC1 EOR FAC2)
  3121                          LAB_1B9D
  3122  9bd2 a5ac               	LDA	FAC1_e		; get FAC1 exponent
  3123  9bd4 60                 	RTS
  3124                          
  3125                          ; print "..." string to string util area
  3126                          
  3127                          LAB_1BC1
  3128  9bd5 a5c3               	LDA	Bpntrl		; get BASIC execute pointer low byte
  3129  9bd7 a4c4               	LDY	Bpntrh		; get BASIC execute pointer high byte
  3130  9bd9 6900               	ADC	#$00			; add carry to low byte
  3131  9bdb 9001               	BCC	LAB_1BCA		; branch if no overflow
  3132                          
  3133  9bdd c8                 	INY				; increment high byte
  3134                          LAB_1BCA
  3135  9bde 205ba1             	JSR	LAB_20AE		; print " terminated string to Sutill/Sutilh
  3136  9be1 4ce6a4             	JMP	LAB_23F3		; restore BASIC execute pointer from temp and return
  3137                          
  3138                          ; get value from line
  3139                          
  3140                          LAB_GVAL
  3141  9be4 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  3142  9be7 b003               	BCS	LAB_1BAC		; branch if not numeric character
  3143                          
  3144                          					; else numeric string found (e.g. 123)
  3145                          LAB_1BA9
  3146  9be9 4cbda9             	JMP	LAB_2887		; get FAC1 from string and return
  3147                          
  3148                          ; get value from line .. continued
  3149                          
  3150                          					; wasn't a number so ..
  3151                          LAB_1BAC
  3152  9bec aa                 	TAX				; set the flags
  3153  9bed 302f               	BMI	LAB_1BD0		; if -ve go test token values
  3154                          
  3155                          					; else it is either a string, number, variable or (<expr>)
  3156  9bef c924               	CMP	#'$'			; compare with "$"
  3157  9bf1 f0f6               	BEQ	LAB_1BA9		; branch if "$", hex number
  3158                          
  3159  9bf3 c925               	CMP	#'%'			; else compare with "%"
  3160  9bf5 f0f2               	BEQ	LAB_1BA9		; branch if "%", binary number
  3161                          
  3162  9bf7 c92e               	CMP	#'.'			; compare with "."
  3163  9bf9 f0ee               	BEQ	LAB_1BA9		; if so get FAC1 from string and return (e.g. was .123)
  3164                          
  3165                          					; it wasn't any sort of number so ..
  3166  9bfb c922               	CMP	#$22			; compare with "
  3167  9bfd f0d6               	BEQ	LAB_1BC1		; branch if open quote
  3168                          
  3169                          					; wasn't any sort of number so ..
  3170                          
  3171                          ; evaluate expression within parentheses
  3172                          
  3173  9bff c928               	CMP	#'('			; compare with "("
  3174  9c01 d04f               	BNE	LAB_1C18		; if not "(" get (var), return value in FAC1 and $ flag
  3175                          
  3176                          LAB_1BF7
  3177  9c03 20009b             	JSR	LAB_EVEZ		; evaluate expression, no decrement
  3178                          
  3179                          ; all the 'scan for' routines return the character after the sought character
  3180                          
  3181                          ; scan for ")" , else do syntax error then warm start
  3182                          
  3183                          LAB_1BFB
  3184  9c06 a929               	LDA	#$29			; load A with ")"
  3185                          
  3186                          ; scan for CHR$(A) , else do syntax error then warm start
  3187                          
  3188                          LAB_SCCA
  3189  9c08 a000               	LDY	#$00			; clear index
  3190  9c0a d1c3               	CMP	(Bpntrl),Y		; check next byte is = A
  3191  9c0c d00b               	BNE	LAB_SNER		; if not do syntax error then warm start
  3192                          
  3193  9c0e 4cbc00             	JMP	LAB_IGBY		; increment and scan memory then return
  3194                          
  3195                          ; scan for "(" , else do syntax error then warm start
  3196                          
  3197                          LAB_1BFE
  3198  9c11 a928               	LDA	#$28			; load A with "("
  3199  9c13 d0f3               	BNE	LAB_SCCA		; scan for CHR$(A), else do syntax error then warm start
  3200                          					; (branch always)
  3201                          
  3202                          ; scan for "," , else do syntax error then warm start
  3203                          
  3204                          LAB_1C01
  3205  9c15 a92c               	LDA	#$2C			; load A with ","
  3206  9c17 d0ef               	BNE	LAB_SCCA		; scan for CHR$(A), else do syntax error then warm start
  3207                          					; (branch always)
  3208                          
  3209                          ; syntax error then warm start
  3210                          
  3211                          LAB_SNER
  3212  9c19 a202               	LDX	#$02			; error code $02 ("Syntax" error)
  3213  9c1b 4c4791             	JMP	LAB_XERR		; do error #X, then warm start
  3214                          
  3215                          ; get value from line .. continued
  3216                          ; do tokens
  3217                          
  3218                          LAB_1BD0
  3219  9c1e c9b9               	CMP	#TK_MINUS		; compare with token for -
  3220  9c20 f029               	BEQ	LAB_1C11		; branch if - token (do set-up for functions)
  3221                          
  3222                          					; wasn't -n so ..
  3223  9c22 c9b8               	CMP	#TK_PLUS		; compare with token for +
  3224  9c24 f0be               	BEQ	LAB_GVAL		; branch if + token (+n = n so ignore leading +)
  3225                          
  3226  9c26 c9b3               	CMP	#TK_NOT		; compare with token for NOT
  3227  9c28 d013               	BNE	LAB_1BE7		; branch if not token for NOT
  3228                          
  3229                          					; was NOT token
  3230                          TK_EQUAL_PLUS	= TK_EQUAL-TK_PLUS
  3231  9c2a a021               	LDY	#TK_EQUAL_PLUS*3	; offset to NOT function
  3232  9c2c d01f               	BNE	LAB_1C13		; do set-up for function then execute (branch always)
  3233                          
  3234                          ; do = compare
  3235                          
  3236                          LAB_EQUAL
  3237  9c2e 20bd9e             	JSR	LAB_EVIR		; evaluate integer expression (no sign check)
  3238  9c31 a5af               	LDA	FAC1_3		; get FAC1 mantissa3
  3239  9c33 49ff               	EOR	#$FF			; invert it
  3240  9c35 a8                 	TAY				; copy it
  3241  9c36 a5ae               	LDA	FAC1_2		; get FAC1 mantissa2
  3242  9c38 49ff               	EOR	#$FF			; invert it
  3243  9c3a 4c70a0             	JMP	LAB_AYFC		; save and convert integer AY to FAC1 and return
  3244                          
  3245                          ; get value from line .. continued
  3246                          
  3247                          					; wasn't +, -, or NOT so ..
  3248                          LAB_1BE7
  3249  9c3d c9b0               	CMP	#TK_FN		; compare with token for FN
  3250  9c3f d003               	BNE	LAB_1BEE		; branch if not token for FN
  3251                          
  3252  9c41 4ccba0             	JMP	LAB_201E		; go evaluate FNx
  3253                          
  3254                          ; get value from line .. continued
  3255                          
  3256                          					; wasn't +, -, NOT or FN so ..
  3257                          LAB_1BEE
  3258  9c44 e9c5               	SBC	#TK_SGN		; subtract with token for SGN
  3259  9c46 b019               	BCS	LAB_1C27		; if a function token go do it
  3260                          
  3261  9c48 4c199c             	JMP	LAB_SNER		; else do syntax error
  3262                          
  3263                          ; set-up for functions
  3264                          
  3265                          LAB_1C11
  3266                          TK_GT_PLUS	= TK_GT-TK_PLUS
  3267  9c4b a01e               	LDY	#TK_GT_PLUS*3	; set offset from base to > operator
  3268                          LAB_1C13
  3269  9c4d 68                 	PLA				; dump return address low byte
  3270  9c4e 68                 	PLA				; dump return address high byte
  3271  9c4f 4c519b             	JMP	LAB_1B1D		; execute function then continue evaluation
  3272                          
  3273                          ; variable name set-up
  3274                          ; get (var), return value in FAC_1 and $ flag
  3275                          
  3276                          LAB_1C18
  3277  9c52 20c19d             	JSR	LAB_GVAR		; get (var) address
  3278  9c55 85ae               	STA	FAC1_2		; save address low byte in FAC1 mantissa2
  3279  9c57 84af               	STY	FAC1_3		; save address high byte in FAC1 mantissa3
  3280  9c59 a65f               	LDX	Dtypef		; get data type flag, $FF=string, $00=numeric
  3281  9c5b 3003               	BMI	LAB_1C25		; if string then return (does RTS)
  3282                          
  3283                          LAB_1C24
  3284  9c5d 4c94a8             	JMP	LAB_UFAC		; unpack memory (AY) into FAC1
  3285                          
  3286                          LAB_1C25
  3287  9c60 60                 	RTS
  3288                          
  3289                          ; get value from line .. continued
  3290                          ; only functions left so ..
  3291                          
  3292                          ; set up function references
  3293                          
  3294                          ; new for V2.0+ this replaces a lot of IF .. THEN .. ELSEIF .. THEN .. that was needed
  3295                          ; to process function calls. now the function vector is computed and pushed on the stack
  3296                          ; and the preprocess offset is read. if the preprocess offset is non zero then the vector
  3297                          ; is calculated and the routine called, if not this routine just does RTS. whichever
  3298                          ; happens the RTS at the end of this routine, or the end of the preprocess routine, calls
  3299                          ; the function code
  3300                          
  3301                          ; this also removes some less than elegant code that was used to bypass type checking
  3302                          ; for functions that returned strings
  3303                          
  3304                          LAB_1C27
  3305  9c61 0a                 	ASL				; *2 (2 bytes per function address)
  3306  9c62 a8                 	TAY				; copy to index
  3307                          
  3308  9c63 b9d4b2             	LDA	LAB_FTBM,Y		; get function jump vector high byte
  3309  9c66 48                 	PHA				; push functions jump vector high byte
  3310  9c67 b9d3b2             	LDA	LAB_FTBL,Y		; get function jump vector low byte
  3311  9c6a 48                 	PHA				; push functions jump vector low byte
  3312                          
  3313  9c6b b98eb2             	LDA	LAB_FTPM,Y		; get function pre process vector high byte
  3314  9c6e f005               	BEQ	LAB_1C56		; skip pre process if null vector
  3315                          
  3316  9c70 48                 	PHA				; push functions pre process vector high byte
  3317  9c71 b98db2             	LDA	LAB_FTPL,Y		; get function pre process vector low byte
  3318  9c74 48                 	PHA				; push functions pre process vector low byte
  3319                          
  3320                          LAB_1C56
  3321  9c75 60                 	RTS				; do function, or pre process, call
  3322                          
  3323                          ; process string expression in parenthesis
  3324                          
  3325                          LAB_PPFS
  3326  9c76 20039c             	JSR	LAB_1BF7		; process expression in parenthesis
  3327  9c79 4ce99a             	JMP	LAB_CTST		; check if source is string then do function,
  3328                          					; else do type mismatch
  3329                          
  3330                          ; process numeric expression in parenthesis
  3331                          
  3332                          LAB_PPFN
  3333  9c7c 20039c             	JSR	LAB_1BF7		; process expression in parenthesis
  3334  9c7f 4ce79a             	JMP	LAB_CTNM		; check if source is numeric then do function,
  3335                          					; else do type mismatch
  3336                          
  3337                          ; set numeric data type and increment BASIC execute pointer
  3338                          
  3339                          LAB_PPBI
  3340  9c82 465f               	LSR	Dtypef		; clear data type flag, $FF=string, $00=numeric
  3341  9c84 4cbc00             	JMP	LAB_IGBY		; increment and scan memory then do function
  3342                          
  3343                          ; process string for LEFT$, RIGHT$ or MID$
  3344                          
  3345                          LAB_LRMS
  3346  9c87 20009b             	JSR	LAB_EVEZ		; evaluate (should be string) expression
  3347  9c8a 20159c             	JSR	LAB_1C01		; scan for ",", else do syntax error then warm start
  3348  9c8d 20e99a             	JSR	LAB_CTST		; check if source is string, else do type mismatch
  3349                          
  3350  9c90 68                 	PLA				; get function jump vector low byte
  3351  9c91 aa                 	TAX				; save functions jump vector low byte
  3352  9c92 68                 	PLA				; get function jump vector high byte
  3353  9c93 a8                 	TAY				; save functions jump vector high byte
  3354  9c94 a5af               	LDA	des_ph		; get descriptor pointer high byte
  3355  9c96 48                 	PHA				; push string pointer high byte
  3356  9c97 a5ae               	LDA	des_pl		; get descriptor pointer low byte
  3357  9c99 48                 	PHA				; push string pointer low byte
  3358  9c9a 98                 	TYA				; get function jump vector high byte back
  3359  9c9b 48                 	PHA				; save functions jump vector high byte
  3360  9c9c 8a                 	TXA				; get function jump vector low byte back
  3361  9c9d 48                 	PHA				; save functions jump vector low byte
  3362  9c9e 20a3a4             	JSR	LAB_GTBY		; get byte parameter
  3363  9ca1 8a                 	TXA				; copy byte parameter to A
  3364  9ca2 60                 	RTS				; go do function
  3365                          
  3366                          ; process numeric expression(s) for BIN$ or HEX$
  3367                          
  3368                          LAB_BHSS
  3369  9ca3 20009b             	JSR	LAB_EVEZ		; process expression
  3370  9ca6 20e79a             	JSR	LAB_CTNM		; check if source is numeric, else do type mismatch
  3371  9ca9 a5ac               	LDA	FAC1_e		; get FAC1 exponent
  3372  9cab c998               	CMP	#$98			; compare with exponent = 2^24
  3373  9cad b020               	BCS	LAB_BHER		; branch if n>=2^24 (is too big)
  3374                          
  3375  9caf 2067a9             	JSR	LAB_2831		; convert FAC1 floating-to-fixed
  3376  9cb2 a202               	LDX	#$02			; 3 bytes to do
  3377                          LAB_CFAC
  3378  9cb4 b5ad               	LDA	FAC1_1,X		; get byte from FAC1
  3379  9cb6 9511               	STA	nums_1,X		; save byte to temp
  3380  9cb8 ca                 	DEX				; decrement index
  3381  9cb9 10f9               	BPL	LAB_CFAC		; copy FAC1 mantissa to temp
  3382                          
  3383  9cbb 20c200             	JSR	LAB_GBYT		; get next BASIC byte
  3384  9cbe a200               	LDX	#$00			; set default to no leading "0"s
  3385  9cc0 c929               	CMP	#')'			; compare with close bracket
  3386  9cc2 f00a               	BEQ	LAB_1C54		; if ")" go do rest of function
  3387                          
  3388  9cc4 20f5a4             	JSR	LAB_SCGB		; scan for "," and get byte
  3389  9cc7 20c200             	JSR	LAB_GBYT		; get last byte back
  3390  9cca c929               	CMP	#')'			; is next character )
  3391  9ccc d001               	BNE	LAB_BHER		; if not ")" go do error
  3392                          
  3393                          LAB_1C54
  3394  9cce 60                 	RTS				; else do function
  3395                          
  3396                          LAB_BHER
  3397  9ccf 4c409f             	JMP	LAB_FCER		; do function call error then warm start
  3398                          
  3399                          ; perform EOR
  3400                          
  3401                          ; added operator format is the same as AND or OR, precedence is the same as OR
  3402                          
  3403                          ; this bit worked first time but it took a while to sort out the operator table
  3404                          ; pointers and offsets afterwards!
  3405                          
  3406                          LAB_EOR
  3407  9cd2 20f99c             	JSR	GetFirst		; get first integer expression (no sign check)
  3408  9cd5 455b               	EOR	XOAw_l		; EOR with expression 1 low byte
  3409  9cd7 a8                 	TAY				; save in Y
  3410  9cd8 a5ae               	LDA	FAC1_2		; get FAC1 mantissa2
  3411  9cda 455c               	EOR	XOAw_h		; EOR with expression 1 high byte
  3412  9cdc 4c70a0             	JMP	LAB_AYFC		; save and convert integer AY to FAC1 and return
  3413                          
  3414                          ; perform OR
  3415                          
  3416                          LAB_OR
  3417  9cdf 20f99c             	JSR	GetFirst		; get first integer expression (no sign check)
  3418  9ce2 055b               	ORA	XOAw_l		; OR with expression 1 low byte
  3419  9ce4 a8                 	TAY				; save in Y
  3420  9ce5 a5ae               	LDA	FAC1_2		; get FAC1 mantissa2
  3421  9ce7 055c               	ORA	XOAw_h		; OR with expression 1 high byte
  3422  9ce9 4c70a0             	JMP	LAB_AYFC		; save and convert integer AY to FAC1 and return
  3423                          
  3424                          ; perform AND
  3425                          
  3426                          LAB_AND
  3427  9cec 20f99c             	JSR	GetFirst		; get first integer expression (no sign check)
  3428  9cef 255b               	AND	XOAw_l		; AND with expression 1 low byte
  3429  9cf1 a8                 	TAY				; save in Y
  3430  9cf2 a5ae               	LDA	FAC1_2		; get FAC1 mantissa2
  3431  9cf4 255c               	AND	XOAw_h		; AND with expression 1 high byte
  3432  9cf6 4c70a0             	JMP	LAB_AYFC		; save and convert integer AY to FAC1 and return
  3433                          
  3434                          ; get first value for OR, AND or EOR
  3435                          
  3436                          GetFirst
  3437  9cf9 20bd9e             	JSR	LAB_EVIR		; evaluate integer expression (no sign check)
  3438  9cfc a5ae               	LDA	FAC1_2		; get FAC1 mantissa2
  3439  9cfe 855c               	STA	XOAw_h		; save it
  3440  9d00 a5af               	LDA	FAC1_3		; get FAC1 mantissa3
  3441  9d02 855b               	STA	XOAw_l		; save it
  3442  9d04 20daa5             	JSR	LAB_279B		; copy FAC2 to FAC1 (get 2nd value in expression)
  3443  9d07 20bd9e             	JSR	LAB_EVIR		; evaluate integer expression (no sign check)
  3444  9d0a a5af               	LDA	FAC1_3		; get FAC1 mantissa3
  3445                          LAB_1C95
  3446  9d0c 60                 	RTS
  3447                          
  3448                          ; perform comparisons
  3449                          
  3450                          ; do < compare
  3451                          
  3452                          LAB_LTHAN
  3453  9d0d 20ea9a             	JSR	LAB_CKTM		; type match check, set C for string
  3454  9d10 b013               	BCS	LAB_1CAE		; branch if string
  3455                          
  3456                          					; do numeric < compare
  3457  9d12 a5b7               	LDA	FAC2_s		; get FAC2 sign (b7)
  3458  9d14 097f               	ORA	#$7F			; set all non sign bits
  3459  9d16 25b4               	AND	FAC2_1		; and FAC2 mantissa1 (AND in sign bit)
  3460  9d18 85b4               	STA	FAC2_1		; save FAC2 mantissa1
  3461  9d1a a9b3               	LDA	#<FAC2_e		; set pointer low byte to FAC2
  3462  9d1c a000               	LDY	#>FAC2_e		; set pointer high byte to FAC2
  3463  9d1e 202ea9             	JSR	LAB_27F8		; compare FAC1 with FAC2 (AY)
  3464  9d21 aa                 	TAX				; copy result
  3465  9d22 4c569d             	JMP	LAB_1CE1		; go evaluate result
  3466                          
  3467                          					; do string < compare
  3468                          LAB_1CAE
  3469  9d25 465f               	LSR	Dtypef		; clear data type flag, $FF=string, $00=numeric
  3470  9d27 c69b               	DEC	comp_f		; clear < bit in compare function flag
  3471  9d29 2055a3             	JSR	LAB_22B6		; pop string off descriptor stack, or from top of string
  3472                          					; space returns with A = length, X=pointer low byte,
  3473                          					; Y=pointer high byte
  3474  9d2c 85ac               	STA	str_ln		; save length
  3475  9d2e 86ad               	STX	str_pl		; save string pointer low byte
  3476  9d30 84ae               	STY	str_ph		; save string pointer high byte
  3477  9d32 a5b5               	LDA	FAC2_2		; get descriptor pointer low byte
  3478  9d34 a4b6               	LDY	FAC2_3		; get descriptor pointer high byte
  3479  9d36 2059a3             	JSR	LAB_22BA		; pop (YA) descriptor off stack or from top of string space
  3480                          					; returns with A = length, X=pointer low byte,
  3481                          					; Y=pointer high byte
  3482  9d39 86b5               	STX	FAC2_2		; save string pointer low byte
  3483  9d3b 84b6               	STY	FAC2_3		; save string pointer high byte
  3484  9d3d aa                 	TAX				; copy length
  3485  9d3e 38                 	SEC				; set carry for subtract
  3486  9d3f e5ac               	SBC	str_ln		; subtract string 1 length
  3487  9d41 f008               	BEQ	LAB_1CD6		; branch if str 1 length = string 2 length
  3488                          
  3489  9d43 a901               	LDA	#$01			; set str 1 length > string 2 length
  3490  9d45 9004               	BCC	LAB_1CD6		; branch if so
  3491                          
  3492  9d47 a6ac               	LDX	str_ln		; get string 1 length
  3493  9d49 a9ff               	LDA	#$FF			; set str 1 length < string 2 length
  3494                          LAB_1CD6
  3495  9d4b 85b0               	STA	FAC1_s		; save length compare
  3496  9d4d a0ff               	LDY	#$FF			; set index
  3497  9d4f e8                 	INX				; adjust for loop
  3498                          LAB_1CDB
  3499  9d50 c8                 	INY				; increment index
  3500  9d51 ca                 	DEX				; decrement count
  3501  9d52 d007               	BNE	LAB_1CE6		; branch if still bytes to do
  3502                          
  3503  9d54 a6b0               	LDX	FAC1_s		; get length compare back
  3504                          LAB_1CE1
  3505  9d56 300f               	BMI	LAB_1CF2		; branch if str 1 < str 2
  3506                          
  3507  9d58 18                 	CLC				; flag str 1 <= str 2
  3508  9d59 900c               	BCC	LAB_1CF2		; go evaluate result
  3509                          
  3510                          LAB_1CE6
  3511  9d5b b1b5               	LDA	(FAC2_2),Y		; get string 2 byte
  3512  9d5d d1ad               	CMP	(FAC1_1),Y		; compare with string 1 byte
  3513  9d5f f0ef               	BEQ	LAB_1CDB		; loop if bytes =
  3514                          
  3515  9d61 a2ff               	LDX	#$FF			; set str 1 < string 2
  3516  9d63 b002               	BCS	LAB_1CF2		; branch if so
  3517                          
  3518  9d65 a201               	LDX	#$01			;  set str 1 > string 2
  3519                          LAB_1CF2
  3520  9d67 e8                 	INX				; x = 0, 1 or 2
  3521  9d68 8a                 	TXA				; copy to A
  3522  9d69 2a                 	ROL				; *2 (1, 2 or 4)
  3523  9d6a 2563               	AND	Cflag			; AND with comparison evaluation flag
  3524  9d6c f002               	BEQ	LAB_1CFB		; branch if 0 (compare is false)
  3525                          
  3526  9d6e a9ff               	LDA	#$FF			; else set result true
  3527                          LAB_1CFB
  3528  9d70 4c11a9             	JMP	LAB_27DB		; save A as integer byte and return
  3529                          
  3530                          LAB_1CFE
  3531  9d73 20159c             	JSR	LAB_1C01		; scan for ",", else do syntax error then warm start
  3532                          
  3533                          ; perform DIM
  3534                          
  3535                          LAB_DIM
  3536  9d76 aa                 	TAX				; copy "DIM" flag to X
  3537  9d77 20c69d             	JSR	LAB_1D10		; search for variable
  3538  9d7a 20c200             	JSR	LAB_GBYT		; scan memory
  3539  9d7d d0f4               	BNE	LAB_1CFE		; scan for "," and loop if not null
  3540                          
  3541  9d7f 60                 	RTS
  3542                          
  3543                          ; perform << (left shift)
  3544                          
  3545                          LAB_LSHIFT
  3546  9d80 20b69d             	JSR	GetPair		; get integer expression and byte (no sign check)
  3547  9d83 a5ae               	LDA	FAC1_2		; get expression high byte
  3548  9d85 a678               	LDX	TempB			; get shift count
  3549  9d87 f022               	BEQ	NoShift		; branch if zero
  3550                          
  3551  9d89 e010               	CPX	#$10			; compare bit count with 16d
  3552  9d8b b023               	BCS	TooBig		; branch if >=
  3553                          
  3554                          Ls_loop
  3555  9d8d 06af               	ASL	FAC1_3		; shift low byte
  3556  9d8f 2a                 	ROL				; shift high byte
  3557  9d90 ca                 	DEX				; decrement bit count
  3558  9d91 d0fa               	BNE	Ls_loop		; loop if shift not complete
  3559                          
  3560  9d93 a4af               	LDY	FAC1_3		; get expression low byte
  3561  9d95 4c70a0             	JMP	LAB_AYFC		; save and convert integer AY to FAC1 and return
  3562                          
  3563                          ; perform >> (right shift)
  3564                          
  3565                          LAB_RSHIFT
  3566  9d98 20b69d             	JSR	GetPair		; get integer expression and byte (no sign check)
  3567  9d9b a5ae               	LDA	FAC1_2		; get expression high byte
  3568  9d9d a678               	LDX	TempB			; get shift count
  3569  9d9f f00a               	BEQ	NoShift		; branch if zero
  3570                          
  3571  9da1 e010               	CPX	#$10			; compare bit count with 16d
  3572  9da3 b00b               	BCS	TooBig		; branch if >=
  3573                          
  3574                          Rs_loop
  3575  9da5 4a                 	LSR				; shift high byte
  3576  9da6 66af               	ROR	FAC1_3		; shift low byte
  3577  9da8 ca                 	DEX				; decrement bit count
  3578  9da9 d0fa               	BNE	Rs_loop		; loop if shift not complete
  3579                          
  3580                          NoShift
  3581  9dab a4af               	LDY	FAC1_3		; get expression low byte
  3582  9dad 4c70a0             	JMP	LAB_AYFC		; save and convert integer AY to FAC1 and return
  3583                          
  3584                          TooBig
  3585  9db0 a900               	LDA	#$00			; clear high byte
  3586  9db2 a8                 	TAY				; copy to low byte
  3587  9db3 4c70a0             	JMP	LAB_AYFC		; save and convert integer AY to FAC1 and return
  3588                          
  3589                          GetPair
  3590  9db6 20a6a4             	JSR	LAB_EVBY		; evaluate byte expression, result in X
  3591  9db9 8678               	STX	TempB			; save it
  3592  9dbb 20daa5             	JSR	LAB_279B		; copy FAC2 to FAC1 (get 2nd value in expression)
  3593  9dbe 4cbd9e             	JMP	LAB_EVIR		; evaluate integer expression (no sign check)
  3594                          
  3595                          ; search for variable
  3596                          
  3597                          ; return pointer to variable in Cvaral/Cvarah
  3598                          
  3599                          LAB_GVAR
  3600  9dc1 a200               	LDX	#$00			; set DIM flag = $00
  3601  9dc3 20c200             	JSR	LAB_GBYT		; scan memory (1st character)
  3602                          LAB_1D10
  3603  9dc6 865e               	STX	Defdim		; save DIM flag
  3604                          LAB_1D12
  3605  9dc8 8593               	STA	Varnm1		; save 1st character
  3606  9dca 297f               	AND	#$7F			; clear FN flag bit
  3607  9dcc 20359e             	JSR	LAB_CASC		; check byte, return C=0 if<"A" or >"Z"
  3608  9dcf b003               	BCS	LAB_1D1F		; branch if ok
  3609                          
  3610  9dd1 4c199c             	JMP	LAB_SNER		; else syntax error then warm start
  3611                          
  3612                          					; was variable name so ..
  3613                          LAB_1D1F
  3614  9dd4 a200               	LDX	#$00			; clear 2nd character temp
  3615  9dd6 865f               	STX	Dtypef		; clear data type flag, $FF=string, $00=numeric
  3616  9dd8 20bc00             	JSR	LAB_IGBY		; increment and scan memory (2nd character)
  3617  9ddb 9005               	BCC	LAB_1D2D		; branch if character = "0"-"9" (ok)
  3618                          
  3619                          					; 2nd character wasn't "0" to "9" so ..
  3620  9ddd 20359e             	JSR	LAB_CASC		; check byte, return C=0 if<"A" or >"Z"
  3621  9de0 900b               	BCC	LAB_1D38		; branch if <"A" or >"Z" (go check if string)
  3622                          
  3623                          LAB_1D2D
  3624  9de2 aa                 	TAX				; copy 2nd character
  3625                          
  3626                          					; ignore further (valid) characters in the variable name
  3627                          LAB_1D2E
  3628  9de3 20bc00             	JSR	LAB_IGBY		; increment and scan memory (3rd character)
  3629  9de6 90fb               	BCC	LAB_1D2E		; loop if character = "0"-"9" (ignore)
  3630                          
  3631  9de8 20359e             	JSR	LAB_CASC		; check byte, return C=0 if<"A" or >"Z"
  3632  9deb b0f6               	BCS	LAB_1D2E		; loop if character = "A"-"Z" (ignore)
  3633                          
  3634                          					; check if string variable
  3635                          LAB_1D38
  3636  9ded c924               	CMP	#'$'			; compare with "$"
  3637  9def d00b               	BNE	LAB_1D47		; branch if not string
  3638                          
  3639                          ; to introduce a new variable type (% suffix for integers say) then this branch
  3640                          ; will need to go to that check and then that branch, if it fails, go to LAB_1D47
  3641                          
  3642                          					; type is string
  3643  9df1 a9ff               	LDA	#$FF			; set data type = string
  3644  9df3 855f               	STA	Dtypef		; set data type flag, $FF=string, $00=numeric
  3645  9df5 8a                 	TXA				; get 2nd character back
  3646  9df6 0980               	ORA	#$80			; set top bit (indicate string var)
  3647  9df8 aa                 	TAX				; copy back to 2nd character temp
  3648  9df9 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  3649                          
  3650                          ; after we have determined the variable type we need to come back here to determine
  3651                          ; if it's an array of type. this would plug in a%(b[,c[,d]])) integer arrays nicely
  3652                          
  3653                          
  3654                          LAB_1D47				; gets here with character after var name in A
  3655  9dfc 8694               	STX	Varnm2		; save 2nd character
  3656  9dfe 0561               	ORA	Sufnxf		; or with subscript/FNX flag (or FN name)
  3657  9e00 c928               	CMP	#'('			; compare with "("
  3658  9e02 d003               	BNE	LAB_1D53		; branch if not "("
  3659                          
  3660  9e04 4ccf9e             	JMP	LAB_1E17		; go find, or make, array
  3661                          
  3662                          ; either find or create var
  3663                          ; var name (1st two characters only!) is in Varnm1,Varnm2
  3664                          
  3665                          					; variable name wasn't var(... so look for plain var
  3666                          LAB_1D53
  3667  9e07 a900               	LDA	#$00			; clear A
  3668  9e09 8561               	STA	Sufnxf		; clear subscript/FNX flag
  3669  9e0b a57b               	LDA	Svarl			; get start of vars low byte
  3670  9e0d a67c               	LDX	Svarh			; get start of vars high byte
  3671  9e0f a000               	LDY	#$00			; clear index
  3672                          LAB_1D5D
  3673  9e11 86ab               	STX	Vrschh		; save search address high byte
  3674                          LAB_1D5F
  3675  9e13 85aa               	STA	Vrschl		; save search address low byte
  3676  9e15 e47e               	CPX	Sarryh		; compare high address with var space end
  3677  9e17 d004               	BNE	LAB_1D69		; skip next compare if <>
  3678                          
  3679                          					; high addresses were = so compare low addresses
  3680  9e19 c57d               	CMP	Sarryl		; compare low address with var space end
  3681  9e1b f02c               	BEQ	LAB_1D8B		; if not found go make new var
  3682                          
  3683                          LAB_1D69
  3684  9e1d a593               	LDA	Varnm1		; get 1st character of var to find
  3685  9e1f d1aa               	CMP	(Vrschl),Y		; compare with variable name 1st character
  3686  9e21 d008               	BNE	LAB_1D77		; branch if no match
  3687                          
  3688                          					; 1st characters match so compare 2nd characters
  3689  9e23 a594               	LDA	Varnm2		; get 2nd character of var to find
  3690  9e25 c8                 	INY				; index to point to variable name 2nd character
  3691  9e26 d1aa               	CMP	(Vrschl),Y		; compare with variable name 2nd character
  3692  9e28 f069               	BEQ	LAB_1DD7		; branch if match (found var)
  3693                          
  3694  9e2a 88                 	DEY				; else decrement index (now = $00)
  3695                          LAB_1D77
  3696  9e2b 18                 	CLC				; clear carry for add
  3697  9e2c a5aa               	LDA	Vrschl		; get search address low byte
  3698  9e2e 6906               	ADC	#$06			; +6 (offset to next var name)
  3699  9e30 90e1               	BCC	LAB_1D5F		; loop if no overflow to high byte
  3700                          
  3701  9e32 e8                 	INX				; else increment high byte
  3702  9e33 d0dc               	BNE	LAB_1D5D		; loop always (RAM doesn't extend to $FFFF !)
  3703                          
  3704                          ; check byte, return C=0 if<"A" or >"Z" or "a" to "z"
  3705                          
  3706                          LAB_CASC
  3707  9e35 c961               	CMP	#'a'			; compare with "a"
  3708  9e37 b00a               	BCS	LAB_1D83		; go check <"z"+1
  3709                          
  3710                          ; check byte, return C=0 if<"A" or >"Z"
  3711                          
  3712                          LAB_1D82
  3713  9e39 c941               	CMP	#'A'			; compare with "A"
  3714  9e3b 9005               	BCC	LAB_1D8A		; exit if less
  3715                          
  3716                          					; carry is set
  3717  9e3d e95b               	SBC	#$5B			; subtract "Z"+1
  3718  9e3f 38                 	SEC				; set carry
  3719  9e40 e9a5               	SBC	#$A5			; subtract $A5 (restore byte)
  3720                          					; carry clear if byte>$5A
  3721                          LAB_1D8A
  3722  9e42 60                 	RTS
  3723                          
  3724                          LAB_1D83
  3725  9e43 e97b               	SBC	#$7B			; subtract "z"+1
  3726  9e45 38                 	SEC				; set carry
  3727  9e46 e985               	SBC	#$85			; subtract $85 (restore byte)
  3728                          					; carry clear if byte>$7A
  3729  9e48 60                 	RTS
  3730                          
  3731                          					; reached end of variable mem without match
  3732                          					; .. so create new variable
  3733                          LAB_1D8B
  3734  9e49 68                 	PLA				; pop return address low byte
  3735  9e4a 48                 	PHA				; push return address low byte
  3736                          LAB_1C18p2	= LAB_1C18+2
  3737  9e4b c954               	CMP	#<LAB_1C18p2	; compare with expected calling routine return low byte
  3738  9e4d d005               	BNE	LAB_1D98		; if not get (var) go create new var
  3739                          
  3740                          ; This will only drop through if the call was from LAB_1C18 and is only called
  3741                          ; from there if it is searching for a variable from the RHS of a LET a=b statement
  3742                          ; it prevents the creation of variables not assigned a value.
  3743                          
  3744                          ; value returned by this is either numeric zero (exponent byte is $00) or null string
  3745                          ; (descriptor length byte is $00). in fact a pointer to any $00 byte would have done.
  3746                          
  3747                          ; doing this saves 6 bytes of variable memory and 168 machine cycles of time
  3748                          
  3749                          ; this is where you would put the undefined variable error call e.g.
  3750                          
  3751                          ;					; variable doesn't exist so flag error
  3752                          ;	LDX	#$24			; error code $24 ("undefined variable" error)
  3753                          ;	JMP	LAB_XERR		; do error #X then warm start
  3754                          
  3755                          ; the above code has been tested and works a treat! (it replaces the three code lines
  3756                          ; below)
  3757                          
  3758                          					; else return dummy null value
  3759  9e4f a90d               	LDA	#<LAB_1D96		; low byte point to $00,$00
  3760                          					; (uses part of misc constants table)
  3761  9e51 a0b2               	LDY	#>LAB_1D96		; high byte point to $00,$00
  3762  9e53 60                 	RTS
  3763                          
  3764                          					; create new numeric variable
  3765                          LAB_1D98
  3766  9e54 a57d               	LDA	Sarryl		; get var mem end low byte
  3767  9e56 a47e               	LDY	Sarryh		; get var mem end high byte
  3768  9e58 85aa               	STA	Ostrtl		; save old block start low byte
  3769  9e5a 84ab               	STY	Ostrth		; save old block start high byte
  3770  9e5c a57f               	LDA	Earryl		; get array mem end low byte
  3771  9e5e a480               	LDY	Earryh		; get array mem end high byte
  3772  9e60 85a6               	STA	Obendl		; save old block end low byte
  3773  9e62 84a7               	STY	Obendh		; save old block end high byte
  3774  9e64 18                 	CLC				; clear carry for add
  3775  9e65 6906               	ADC	#$06			; +6 (space for one var)
  3776  9e67 9001               	BCC	LAB_1DAE		; branch if no overflow to high byte
  3777                          
  3778  9e69 c8                 	INY				; else increment high byte
  3779                          LAB_1DAE
  3780  9e6a 85a4               	STA	Nbendl		; set new block end low byte
  3781  9e6c 84a5               	STY	Nbendh		; set new block end high byte
  3782  9e6e 20cc90             	JSR	LAB_11CF		; open up space in memory
  3783  9e71 a5a4               	LDA	Nbendl		; get new start low byte
  3784  9e73 a4a5               	LDY	Nbendh		; get new start high byte (-$100)
  3785  9e75 c8                 	INY				; correct high byte
  3786  9e76 857d               	STA	Sarryl		; save new var mem end low byte
  3787  9e78 847e               	STY	Sarryh		; save new var mem end high byte
  3788  9e7a a000               	LDY	#$00			; clear index
  3789  9e7c a593               	LDA	Varnm1		; get var name 1st character
  3790  9e7e 91aa               	STA	(Vrschl),Y		; save var name 1st character
  3791  9e80 c8                 	INY				; increment index
  3792  9e81 a594               	LDA	Varnm2		; get var name 2nd character
  3793  9e83 91aa               	STA	(Vrschl),Y		; save var name 2nd character
  3794  9e85 a900               	LDA	#$00			; clear A
  3795  9e87 c8                 	INY				; increment index
  3796  9e88 91aa               	STA	(Vrschl),Y		; initialise var byte
  3797  9e8a c8                 	INY				; increment index
  3798  9e8b 91aa               	STA	(Vrschl),Y		; initialise var byte
  3799  9e8d c8                 	INY				; increment index
  3800  9e8e 91aa               	STA	(Vrschl),Y		; initialise var byte
  3801  9e90 c8                 	INY				; increment index
  3802  9e91 91aa               	STA	(Vrschl),Y		; initialise var byte
  3803                          
  3804                          					; found a match for var ((Vrschl) = ptr)
  3805                          LAB_1DD7
  3806  9e93 a5aa               	LDA	Vrschl		; get var address low byte
  3807  9e95 18                 	CLC				; clear carry for add
  3808  9e96 6902               	ADC	#$02			; +2 (offset past var name bytes)
  3809  9e98 a4ab               	LDY	Vrschh		; get var address high byte
  3810  9e9a 9001               	BCC	LAB_1DE1		; branch if no overflow from add
  3811                          
  3812  9e9c c8                 	INY				; else increment high byte
  3813                          LAB_1DE1
  3814  9e9d 8595               	STA	Cvaral		; save current var address low byte
  3815  9e9f 8496               	STY	Cvarah		; save current var address high byte
  3816  9ea1 60                 	RTS
  3817                          
  3818                          ; set-up array pointer (Adatal/h) to first element in array
  3819                          ; set Adatal,Adatah to Astrtl,Astrth+2*Dimcnt+#$05
  3820                          
  3821                          LAB_1DE6
  3822  9ea2 a55d               	LDA	Dimcnt		; get # of dimensions (1, 2 or 3)
  3823  9ea4 0a                 	ASL				; *2 (also clears the carry !)
  3824  9ea5 6905               	ADC	#$05			; +5 (result is 7, 9 or 11 here)
  3825  9ea7 65aa               	ADC	Astrtl		; add array start pointer low byte
  3826  9ea9 a4ab               	LDY	Astrth		; get array pointer high byte
  3827  9eab 9001               	BCC	LAB_1DF2		; branch if no overflow
  3828                          
  3829  9ead c8                 	INY				; else increment high byte
  3830                          LAB_1DF2
  3831  9eae 85a4               	STA	Adatal		; save array data pointer low byte
  3832  9eb0 84a5               	STY	Adatah		; save array data pointer high byte
  3833  9eb2 60                 	RTS
  3834                          
  3835                          ; evaluate integer expression
  3836                          
  3837                          LAB_EVIN
  3838  9eb3 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  3839  9eb6 20e49a             	JSR	LAB_EVNM		; evaluate expression and check is numeric,
  3840                          					; else do type mismatch
  3841                          
  3842                          ; evaluate integer expression (no check)
  3843                          
  3844                          LAB_EVPI
  3845  9eb9 a5b0               	LDA	FAC1_s		; get FAC1 sign (b7)
  3846  9ebb 300d               	BMI	LAB_1E12		; do function call error if -ve
  3847                          
  3848                          ; evaluate integer expression (no sign check)
  3849                          
  3850                          LAB_EVIR
  3851  9ebd a5ac               	LDA	FAC1_e		; get FAC1 exponent
  3852  9ebf c990               	CMP	#$90			; compare with exponent = 2^16 (n>2^15)
  3853  9ec1 9009               	BCC	LAB_1E14		; branch if n<2^16 (is ok)
  3854                          
  3855  9ec3 a914               	LDA	#<LAB_1DF7		; set pointer low byte to -32768
  3856  9ec5 a0b2               	LDY	#>LAB_1DF7		; set pointer high byte to -32768
  3857  9ec7 202ea9             	JSR	LAB_27F8		; compare FAC1 with (AY)
  3858                          LAB_1E12
  3859  9eca d074               	BNE	LAB_FCER		; if <> do function call error then warm start
  3860                          
  3861                          LAB_1E14
  3862  9ecc 4c67a9             	JMP	LAB_2831		; convert FAC1 floating-to-fixed and return
  3863                          
  3864                          ; find or make array
  3865                          
  3866                          LAB_1E17
  3867  9ecf a55e               	LDA	Defdim		; get DIM flag
  3868  9ed1 48                 	PHA				; push it
  3869  9ed2 a55f               	LDA	Dtypef		; get data type flag, $FF=string, $00=numeric
  3870  9ed4 48                 	PHA				; push it
  3871  9ed5 a000               	LDY	#$00			; clear dimensions count
  3872                          
  3873                          ; now get the array dimension(s) and stack it (them) before the data type and DIM flag
  3874                          
  3875                          LAB_1E1F
  3876  9ed7 98                 	TYA				; copy dimensions count
  3877  9ed8 48                 	PHA				; save it
  3878  9ed9 a594               	LDA	Varnm2		; get array name 2nd byte
  3879  9edb 48                 	PHA				; save it
  3880  9edc a593               	LDA	Varnm1		; get array name 1st byte
  3881  9ede 48                 	PHA				; save it
  3882  9edf 20b39e             	JSR	LAB_EVIN		; evaluate integer expression
  3883  9ee2 68                 	PLA				; pull array name 1st byte
  3884  9ee3 8593               	STA	Varnm1		; restore array name 1st byte
  3885  9ee5 68                 	PLA				; pull array name 2nd byte
  3886  9ee6 8594               	STA	Varnm2		; restore array name 2nd byte
  3887  9ee8 68                 	PLA				; pull dimensions count
  3888  9ee9 a8                 	TAY				; restore it
  3889  9eea ba                 	TSX				; copy stack pointer
  3890  9eeb bd0201             	LDA	LAB_STAK+2,X	; get DIM flag
  3891  9eee 48                 	PHA				; push it
  3892  9eef bd0101             	LDA	LAB_STAK+1,X	; get data type flag
  3893  9ef2 48                 	PHA				; push it
  3894  9ef3 a5ae               	LDA	FAC1_2		; get this dimension size high byte
  3895  9ef5 9d0201             	STA	LAB_STAK+2,X	; stack before flag bytes
  3896  9ef8 a5af               	LDA	FAC1_3		; get this dimension size low byte
  3897  9efa 9d0101             	STA	LAB_STAK+1,X	; stack before flag bytes
  3898  9efd c8                 	INY				; increment dimensions count
  3899  9efe 20c200             	JSR	LAB_GBYT		; scan memory
  3900  9f01 c92c               	CMP	#','			; compare with ","
  3901  9f03 f0d2               	BEQ	LAB_1E1F		; if found go do next dimension
  3902                          
  3903  9f05 845d               	STY	Dimcnt		; store dimensions count
  3904  9f07 20069c             	JSR	LAB_1BFB		; scan for ")" , else do syntax error then warm start
  3905  9f0a 68                 	PLA				; pull data type flag
  3906  9f0b 855f               	STA	Dtypef		; restore data type flag, $FF=string, $00=numeric
  3907  9f0d 68                 	PLA				; pull DIM flag
  3908  9f0e 855e               	STA	Defdim		; restore DIM flag
  3909  9f10 a67d               	LDX	Sarryl		; get array mem start low byte
  3910  9f12 a57e               	LDA	Sarryh		; get array mem start high byte
  3911                          
  3912                          ; now check to see if we are at the end of array memory (we would be if there were
  3913                          ; no arrays).
  3914                          
  3915                          LAB_1E5C
  3916  9f14 86aa               	STX	Astrtl		; save as array start pointer low byte
  3917  9f16 85ab               	STA	Astrth		; save as array start pointer high byte
  3918  9f18 c580               	CMP	Earryh		; compare with array mem end high byte
  3919  9f1a d004               	BNE	LAB_1E68		; branch if not reached array mem end
  3920                          
  3921  9f1c e47f               	CPX	Earryl		; else compare with array mem end low byte
  3922  9f1e f039               	BEQ	LAB_1EA1		; go build array if not found
  3923                          
  3924                          					; search for array
  3925                          LAB_1E68
  3926  9f20 a000               	LDY	#$00			; clear index
  3927  9f22 b1aa               	LDA	(Astrtl),Y		; get array name first byte
  3928  9f24 c8                 	INY				; increment index to second name byte
  3929  9f25 c593               	CMP	Varnm1		; compare with this array name first byte
  3930  9f27 d006               	BNE	LAB_1E77		; branch if no match
  3931                          
  3932  9f29 a594               	LDA	Varnm2		; else get this array name second byte
  3933  9f2b d1aa               	CMP	(Astrtl),Y		; compare with array name second byte
  3934  9f2d f016               	BEQ	LAB_1E8D		; array found so branch
  3935                          
  3936                          					; no match
  3937                          LAB_1E77
  3938  9f2f c8                 	INY				; increment index
  3939  9f30 b1aa               	LDA	(Astrtl),Y		; get array size low byte
  3940  9f32 18                 	CLC				; clear carry for add
  3941  9f33 65aa               	ADC	Astrtl		; add array start pointer low byte
  3942  9f35 aa                 	TAX				; copy low byte to X
  3943  9f36 c8                 	INY				; increment index
  3944  9f37 b1aa               	LDA	(Astrtl),Y		; get array size high byte
  3945  9f39 65ab               	ADC	Astrth		; add array mem pointer high byte
  3946  9f3b 90d7               	BCC	LAB_1E5C		; if no overflow go check next array
  3947                          
  3948                          ; do array bounds error
  3949                          
  3950                          LAB_1E85
  3951  9f3d a210               	LDX	#$10			; error code $10 ("Array bounds" error)
  3952  9f3f 2c                 	!text	$2C			; makes next bit BIT LAB_08A2
  3953                          
  3954                          ; do function call error
  3955                          
  3956                          LAB_FCER
  3957  9f40 a208               	LDX	#$08			; error code $08 ("Function call" error)
  3958                          LAB_1E8A
  3959  9f42 4c4791             	JMP	LAB_XERR		; do error #X, then warm start
  3960                          
  3961                          					; found array, are we trying to dimension it?
  3962                          LAB_1E8D
  3963  9f45 a212               	LDX	#$12			; set error $12 ("Double dimension" error)
  3964  9f47 a55e               	LDA	Defdim		; get DIM flag
  3965  9f49 d0f7               	BNE	LAB_1E8A		; if we are trying to dimension it do error #X, then warm
  3966                          					; start
  3967                          
  3968                          ; found the array and we're not dimensioning it so we must find an element in it
  3969                          
  3970  9f4b 20a29e             	JSR	LAB_1DE6		; set-up array pointer (Adatal/h) to first element in array
  3971                          					; (Astrtl,Astrth points to start of array)
  3972  9f4e a55d               	LDA	Dimcnt		; get dimensions count
  3973  9f50 a004               	LDY	#$04			; set index to array's # of dimensions
  3974  9f52 d1aa               	CMP	(Astrtl),Y		; compare with no of dimensions
  3975  9f54 d0e7               	BNE	LAB_1E85		; if wrong do array bounds error, could do "Wrong
  3976                          					; dimensions" error here .. if we want a different
  3977                          					; error message
  3978                          
  3979  9f56 4cdc9f             	JMP	LAB_1F28		; found array so go get element
  3980                          					; (could jump to LAB_1F28 as all LAB_1F24 does is take
  3981                          					; Dimcnt and save it at (Astrtl),Y which is already the
  3982                          					; same or we would have taken the BNE)
  3983                          
  3984                          					; array not found, so build it
  3985                          LAB_1EA1
  3986  9f59 20a29e             	JSR	LAB_1DE6		; set-up array pointer (Adatal/h) to first element in array
  3987                          					; (Astrtl,Astrth points to start of array)
  3988  9f5c 201691             	JSR	LAB_121F		; check available memory, "Out of memory" error if no room
  3989                          					; addr to check is in AY (low/high)
  3990  9f5f a000               	LDY	#$00			; clear Y (don't need to clear A)
  3991  9f61 84bb               	STY	Aspth			; clear array data size high byte
  3992  9f63 a593               	LDA	Varnm1		; get variable name 1st byte
  3993  9f65 91aa               	STA	(Astrtl),Y		; save array name 1st byte
  3994  9f67 c8                 	INY				; increment index
  3995  9f68 a594               	LDA	Varnm2		; get variable name 2nd byte
  3996  9f6a 91aa               	STA	(Astrtl),Y		; save array name 2nd byte
  3997  9f6c a55d               	LDA	Dimcnt		; get dimensions count
  3998  9f6e a004               	LDY	#$04			; index to dimension count
  3999  9f70 84ba               	STY	Asptl			; set array data size low byte (four bytes per element)
  4000  9f72 91aa               	STA	(Astrtl),Y		; set array's dimensions count
  4001                          
  4002                          					; now calculate the size of the data space for the array
  4003  9f74 18                 	CLC				; clear carry for add (clear on subsequent loops)
  4004                          LAB_1EC0
  4005  9f75 a20b               	LDX	#$0B			; set default dimension value low byte
  4006  9f77 a900               	LDA	#$00			; set default dimension value high byte
  4007  9f79 245e               	BIT	Defdim		; test default DIM flag
  4008  9f7b 5007               	BVC	LAB_1ED0		; branch if b6 of Defdim is clear
  4009                          
  4010  9f7d 68                 	PLA				; else pull dimension value low byte
  4011  9f7e 6901               	ADC	#$01			; +1 (allow for zeroeth element)
  4012  9f80 aa                 	TAX				; copy low byte to X
  4013  9f81 68                 	PLA				; pull dimension value high byte
  4014  9f82 6900               	ADC	#$00			; add carry from low byte
  4015                          
  4016                          LAB_1ED0
  4017  9f84 c8                 	INY				; index to dimension value high byte
  4018  9f85 91aa               	STA	(Astrtl),Y		; save dimension value high byte
  4019  9f87 c8                 	INY				; index to dimension value high byte
  4020  9f88 8a                 	TXA				; get dimension value low byte
  4021  9f89 91aa               	STA	(Astrtl),Y		; save dimension value low byte
  4022  9f8b 202ba0             	JSR	LAB_1F7C		; does XY = (Astrtl),Y * (Asptl)
  4023  9f8e 86ba               	STX	Asptl			; save array data size low byte
  4024  9f90 85bb               	STA	Aspth			; save array data size high byte
  4025  9f92 a471               	LDY	ut1_pl		; restore index (saved by subroutine)
  4026  9f94 c65d               	DEC	Dimcnt		; decrement dimensions count
  4027  9f96 d0dd               	BNE	LAB_1EC0		; loop while not = 0
  4028                          
  4029  9f98 65a5               	ADC	Adatah		; add size high byte to first element high byte
  4030                          					; (carry is always clear here)
  4031  9f9a b05d               	BCS	LAB_1F45		; if overflow go do "Out of memory" error
  4032                          
  4033  9f9c 85a5               	STA	Adatah		; save end of array high byte
  4034  9f9e a8                 	TAY				; copy end high byte to Y
  4035  9f9f 8a                 	TXA				; get array size low byte
  4036  9fa0 65a4               	ADC	Adatal		; add array start low byte
  4037  9fa2 9003               	BCC	LAB_1EF3		; branch if no carry
  4038                          
  4039  9fa4 c8                 	INY				; else increment end of array high byte
  4040  9fa5 f052               	BEQ	LAB_1F45		; if overflow go do "Out of memory" error
  4041                          
  4042                          					; set-up mostly complete, now zero the array
  4043                          LAB_1EF3
  4044  9fa7 201691             	JSR	LAB_121F		; check available memory, "Out of memory" error if no room
  4045                          					; addr to check is in AY (low/high)
  4046  9faa 857f               	STA	Earryl		; save array mem end low byte
  4047  9fac 8480               	STY	Earryh		; save array mem end high byte
  4048  9fae a900               	LDA	#$00			; clear byte for array clear
  4049  9fb0 e6bb               	INC	Aspth			; increment array size high byte (now block count)
  4050  9fb2 a4ba               	LDY	Asptl			; get array size low byte (now index to block)
  4051  9fb4 f005               	BEQ	LAB_1F07		; branch if low byte = $00
  4052                          
  4053                          LAB_1F02
  4054  9fb6 88                 	DEY				; decrement index (do 0 to n-1)
  4055  9fb7 91a4               	STA	(Adatal),Y		; zero byte
  4056  9fb9 d0fb               	BNE	LAB_1F02		; loop until this block done
  4057                          
  4058                          LAB_1F07
  4059  9fbb c6a5               	DEC	Adatah		; decrement array pointer high byte
  4060  9fbd c6bb               	DEC	Aspth			; decrement block count high byte
  4061  9fbf d0f5               	BNE	LAB_1F02		; loop until all blocks done
  4062                          
  4063  9fc1 e6a5               	INC	Adatah		; correct for last loop
  4064  9fc3 38                 	SEC				; set carry for subtract
  4065  9fc4 a002               	LDY	#$02			; index to array size low byte
  4066  9fc6 a57f               	LDA	Earryl		; get array mem end low byte
  4067  9fc8 e5aa               	SBC	Astrtl		; subtract array start low byte
  4068  9fca 91aa               	STA	(Astrtl),Y		; save array size low byte
  4069  9fcc c8                 	INY				; index to array size high byte
  4070  9fcd a580               	LDA	Earryh		; get array mem end high byte
  4071  9fcf e5ab               	SBC	Astrth		; subtract array start high byte
  4072  9fd1 91aa               	STA	(Astrtl),Y		; save array size high byte
  4073  9fd3 a55e               	LDA	Defdim		; get default DIM flag
  4074  9fd5 d053               	BNE	LAB_1F7B		; exit (RET) if this was a DIM command
  4075                          
  4076                          					; else, find element
  4077  9fd7 c8                 	INY				; index to # of dimensions
  4078                          
  4079                          LAB_1F24
  4080  9fd8 b1aa               	LDA	(Astrtl),Y		; get array's dimension count
  4081  9fda 855d               	STA	Dimcnt		; save it
  4082                          
  4083                          ; we have found, or built, the array. now we need to find the element
  4084                          
  4085                          LAB_1F28
  4086  9fdc a900               	LDA	#$00			; clear byte
  4087  9fde 85ba               	STA	Asptl			; clear array data pointer low byte
  4088                          LAB_1F2C
  4089  9fe0 85bb               	STA	Aspth			; save array data pointer high byte
  4090  9fe2 c8                 	INY				; increment index (point to array bound high byte)
  4091  9fe3 68                 	PLA				; pull array index low byte
  4092  9fe4 aa                 	TAX				; copy to X
  4093  9fe5 85ae               	STA	FAC1_2		; save index low byte to FAC1 mantissa2
  4094  9fe7 68                 	PLA				; pull array index high byte
  4095  9fe8 85af               	STA	FAC1_3		; save index high byte to FAC1 mantissa3
  4096  9fea d1aa               	CMP	(Astrtl),Y		; compare with array bound high byte
  4097  9fec 900e               	BCC	LAB_1F48		; branch if within bounds
  4098                          
  4099  9fee d006               	BNE	LAB_1F42		; if outside bounds do array bounds error
  4100                          
  4101                          					; else high byte was = so test low bytes
  4102  9ff0 c8                 	INY				; index to array bound low byte
  4103  9ff1 8a                 	TXA				; get array index low byte
  4104  9ff2 d1aa               	CMP	(Astrtl),Y		; compare with array bound low byte
  4105  9ff4 9007               	BCC	LAB_1F49		; branch if within bounds
  4106                          
  4107                          LAB_1F42
  4108  9ff6 4c3d9f             	JMP	LAB_1E85		; else do array bounds error
  4109                          
  4110                          LAB_1F45
  4111  9ff9 4c4591             	JMP	LAB_OMER		; do "Out of memory" error then warm start
  4112                          
  4113                          LAB_1F48
  4114  9ffc c8                 	INY				; index to array bound low byte
  4115                          LAB_1F49
  4116  9ffd a5bb               	LDA	Aspth			; get array data pointer high byte
  4117  9fff 05ba               	ORA	Asptl			; OR with array data pointer low byte
  4118  a001 f00a               	BEQ	LAB_1F5A		; branch if array data pointer = null (skip multiply)
  4119                          
  4120  a003 202ba0             	JSR	LAB_1F7C		; does XY = (Astrtl),Y * (Asptl)
  4121  a006 8a                 	TXA				; get result low byte
  4122  a007 65ae               	ADC	FAC1_2		; add index low byte from FAC1 mantissa2
  4123  a009 aa                 	TAX				; save result low byte
  4124  a00a 98                 	TYA				; get result high byte
  4125  a00b a471               	LDY	ut1_pl		; restore index
  4126                          LAB_1F5A
  4127  a00d 65af               	ADC	FAC1_3		; add index high byte from FAC1 mantissa3
  4128  a00f 86ba               	STX	Asptl			; save array data pointer low byte
  4129  a011 c65d               	DEC	Dimcnt		; decrement dimensions count
  4130  a013 d0cb               	BNE	LAB_1F2C		; loop if dimensions still to do
  4131                          
  4132  a015 06ba               	ASL	Asptl			; array data pointer low byte * 2
  4133  a017 2a                 	ROL				; array data pointer high byte * 2
  4134  a018 06ba               	ASL	Asptl			; array data pointer low byte * 4
  4135  a01a 2a                 	ROL				; array data pointer high byte * 4
  4136  a01b a8                 	TAY				; copy high byte
  4137  a01c a5ba               	LDA	Asptl			; get low byte
  4138  a01e 65a4               	ADC	Adatal		; add array data start pointer low byte
  4139  a020 8595               	STA	Cvaral		; save as current var address low byte
  4140  a022 98                 	TYA				; get high byte back
  4141  a023 65a5               	ADC	Adatah		; add array data start pointer high byte
  4142  a025 8596               	STA	Cvarah		; save as current var address high byte
  4143  a027 a8                 	TAY				; copy high byte to Y
  4144  a028 a595               	LDA	Cvaral		; get current var address low byte
  4145                          LAB_1F7B
  4146  a02a 60                 	RTS
  4147                          
  4148                          ; does XY = (Astrtl),Y * (Asptl)
  4149                          
  4150                          LAB_1F7C
  4151  a02b 8471               	STY	ut1_pl		; save index
  4152  a02d b1aa               	LDA	(Astrtl),Y		; get dimension size low byte
  4153  a02f 8576               	STA	dims_l		; save dimension size low byte
  4154  a031 88                 	DEY				; decrement index
  4155  a032 b1aa               	LDA	(Astrtl),Y		; get dimension size high byte
  4156  a034 8577               	STA	dims_h		; save dimension size high byte
  4157                          
  4158  a036 a910               	LDA	#$10			; count = $10 (16 bit multiply)
  4159  a038 85a8               	STA	numbit		; save bit count
  4160  a03a a200               	LDX	#$00			; clear result low byte
  4161  a03c a000               	LDY	#$00			; clear result high byte
  4162                          LAB_1F8F
  4163  a03e 8a                 	TXA				; get result low byte
  4164  a03f 0a                 	ASL				; *2
  4165  a040 aa                 	TAX				; save result low byte
  4166  a041 98                 	TYA				; get result high byte
  4167  a042 2a                 	ROL				; *2
  4168  a043 a8                 	TAY				; save result high byte
  4169  a044 b0b3               	BCS	LAB_1F45		; if overflow go do "Out of memory" error
  4170                          
  4171  a046 06ba               	ASL	Asptl			; shift multiplier low byte
  4172  a048 26bb               	ROL	Aspth			; shift multiplier high byte
  4173  a04a 900b               	BCC	LAB_1FA8		; skip add if no carry
  4174                          
  4175  a04c 18                 	CLC				; else clear carry for add
  4176  a04d 8a                 	TXA				; get result low byte
  4177  a04e 6576               	ADC	dims_l		; add dimension size low byte
  4178  a050 aa                 	TAX				; save result low byte
  4179  a051 98                 	TYA				; get result high byte
  4180  a052 6577               	ADC	dims_h		; add dimension size high byte
  4181  a054 a8                 	TAY				; save result high byte
  4182  a055 b0a2               	BCS	LAB_1F45		; if overflow go do "Out of memory" error
  4183                          
  4184                          LAB_1FA8
  4185  a057 c6a8               	DEC	numbit		; decrement bit count
  4186  a059 d0e3               	BNE	LAB_1F8F		; loop until all done
  4187                          
  4188  a05b 60                 	RTS
  4189                          
  4190                          ; perform FRE()
  4191                          
  4192                          LAB_FRE
  4193  a05c a55f               	LDA	Dtypef		; get data type flag, $FF=string, $00=numeric
  4194  a05e 1003               	BPL	LAB_1FB4		; branch if numeric
  4195                          
  4196  a060 2055a3             	JSR	LAB_22B6		; pop string off descriptor stack, or from top of string
  4197                          					; space returns with A = length, X=$71=pointer low byte,
  4198                          					; Y=$72=pointer high byte
  4199                          
  4200                          					; FRE(n) was numeric so do this
  4201                          LAB_1FB4
  4202  a063 20f6a1             	JSR	LAB_GARB		; go do garbage collection
  4203  a066 38                 	SEC				; set carry for subtract
  4204  a067 a581               	LDA	Sstorl		; get bottom of string space low byte
  4205  a069 e57f               	SBC	Earryl		; subtract array mem end low byte
  4206  a06b a8                 	TAY				; copy result to Y
  4207  a06c a582               	LDA	Sstorh		; get bottom of string space high byte
  4208  a06e e580               	SBC	Earryh		; subtract array mem end high byte
  4209                          
  4210                          ; save and convert integer AY to FAC1
  4211                          
  4212                          LAB_AYFC
  4213  a070 465f               	LSR	Dtypef		; clear data type flag, $FF=string, $00=numeric
  4214  a072 85ad               	STA	FAC1_1		; save FAC1 mantissa1
  4215  a074 84ae               	STY	FAC1_2		; save FAC1 mantissa2
  4216  a076 a290               	LDX	#$90			; set exponent=2^16 (integer)
  4217  a078 4c19a9             	JMP	LAB_27E3		; set exp=X, clear FAC1_3, normalise and return
  4218                          
  4219                          ; perform POS()
  4220                          
  4221                          LAB_POS
  4222  a07b a40e               	LDY	TPos			; get terminal position
  4223                          
  4224                          ; convert Y to byte in FAC1
  4225                          
  4226                          LAB_1FD0
  4227  a07d a900               	LDA	#$00			; clear high byte
  4228  a07f f0ef               	BEQ	LAB_AYFC		; always save and convert integer AY to FAC1 and return
  4229                          
  4230                          ; check not Direct (used by DEF and INPUT)
  4231                          
  4232                          LAB_CKRN
  4233  a081 a688               	LDX	Clineh		; get current line high byte
  4234  a083 e8                 	INX				; increment it
  4235  a084 d0a4               	BNE	LAB_1F7B		; return if can continue not direct mode
  4236                          
  4237                          					; else do illegal direct error
  4238                          LAB_1FD9
  4239  a086 a216               	LDX	#$16			; error code $16 ("Illegal direct" error)
  4240                          LAB_1FDB
  4241  a088 4c4791             	JMP	LAB_XERR		; go do error #X, then warm start
  4242                          
  4243                          ; perform DEF
  4244                          
  4245                          LAB_DEF
  4246  a08b 20bca0             	JSR	LAB_200B		; check FNx syntax
  4247  a08e 859c               	STA	func_l		; save function pointer low byte
  4248  a090 849d               	STY	func_h		; save function pointer high byte
  4249  a092 2081a0             	JSR	LAB_CKRN		; check not Direct (back here if ok)
  4250  a095 20119c             	JSR	LAB_1BFE		; scan for "(" , else do syntax error then warm start
  4251  a098 a980               	LDA	#$80			; set flag for FNx
  4252  a09a 8561               	STA	Sufnxf		; save subscript/FNx flag
  4253  a09c 20c19d             	JSR	LAB_GVAR		; get (var) address
  4254  a09f 20e79a             	JSR	LAB_CTNM		; check if source is numeric, else do type mismatch
  4255  a0a2 20069c             	JSR	LAB_1BFB		; scan for ")" , else do syntax error then warm start
  4256  a0a5 a9c3               	LDA	#TK_EQUAL		; get = token
  4257  a0a7 20089c             	JSR	LAB_SCCA		; scan for CHR$(A), else do syntax error then warm start
  4258  a0aa a596               	LDA	Cvarah		; get current var address high byte
  4259  a0ac 48                 	PHA				; push it
  4260  a0ad a595               	LDA	Cvaral		; get current var address low byte
  4261  a0af 48                 	PHA				; push it
  4262  a0b0 a5c4               	LDA	Bpntrh		; get BASIC execute pointer high byte
  4263  a0b2 48                 	PHA				; push it
  4264  a0b3 a5c3               	LDA	Bpntrl		; get BASIC execute pointer low byte
  4265  a0b5 48                 	PHA				; push it
  4266  a0b6 20a896             	JSR	LAB_DATA		; go perform DATA
  4267  a0b9 4c2ba1             	JMP	LAB_207A		; put execute pointer and variable pointer into function
  4268                          					; and return
  4269                          
  4270                          ; check FNx syntax
  4271                          
  4272                          LAB_200B
  4273  a0bc a9b0               	LDA	#TK_FN		; get FN" token
  4274  a0be 20089c             	JSR	LAB_SCCA		; scan for CHR$(A) , else do syntax error then warm start
  4275                          					; return character after A
  4276  a0c1 0980               	ORA	#$80			; set FN flag bit
  4277  a0c3 8561               	STA	Sufnxf		; save FN flag so array variable test fails
  4278  a0c5 20c89d             	JSR	LAB_1D12		; search for FN variable
  4279  a0c8 4ce79a             	JMP	LAB_CTNM		; check if source is numeric and return, else do type
  4280                          					; mismatch
  4281                          
  4282                          					; Evaluate FNx
  4283                          LAB_201E
  4284  a0cb 20bca0             	JSR	LAB_200B		; check FNx syntax
  4285  a0ce 48                 	PHA				; push function pointer low byte
  4286  a0cf 98                 	TYA				; copy function pointer high byte
  4287  a0d0 48                 	PHA				; push function pointer high byte
  4288  a0d1 20119c             	JSR	LAB_1BFE		; scan for "(", else do syntax error then warm start
  4289  a0d4 20f89a             	JSR	LAB_EVEX		; evaluate expression
  4290  a0d7 20069c             	JSR	LAB_1BFB		; scan for ")", else do syntax error then warm start
  4291  a0da 20e79a             	JSR	LAB_CTNM		; check if source is numeric, else do type mismatch
  4292  a0dd 68                 	PLA				; pop function pointer high byte
  4293  a0de 859d               	STA	func_h		; restore it
  4294  a0e0 68                 	PLA				; pop function pointer low byte
  4295  a0e1 859c               	STA	func_l		; restore it
  4296  a0e3 a220               	LDX	#$20			; error code $20 ("Undefined function" error)
  4297  a0e5 a003               	LDY	#$03			; index to variable pointer high byte
  4298  a0e7 b19c               	LDA	(func_l),Y		; get variable pointer high byte
  4299  a0e9 f09d               	BEQ	LAB_1FDB		; if zero go do undefined function error
  4300                          
  4301  a0eb 8596               	STA	Cvarah		; save variable address high byte
  4302  a0ed 88                 	DEY				; index to variable address low byte
  4303  a0ee b19c               	LDA	(func_l),Y		; get variable address low byte
  4304  a0f0 8595               	STA	Cvaral		; save variable address low byte
  4305  a0f2 aa                 	TAX				; copy address low byte
  4306                          
  4307                          					; now stack the function variable value before use
  4308  a0f3 c8                 	INY				; index to mantissa_3
  4309                          LAB_2043
  4310  a0f4 b195               	LDA	(Cvaral),Y		; get byte from variable
  4311  a0f6 48                 	PHA				; stack it
  4312  a0f7 88                 	DEY				; decrement index
  4313  a0f8 10fa               	BPL	LAB_2043		; loop until variable stacked
  4314                          
  4315  a0fa a496               	LDY	Cvarah		; get variable address high byte
  4316  a0fc 20bea8             	JSR	LAB_2778		; pack FAC1 (function expression value) into (XY)
  4317                          					; (function variable), return Y=0, always
  4318  a0ff a5c4               	LDA	Bpntrh		; get BASIC execute pointer high byte
  4319  a101 48                 	PHA				; push it
  4320  a102 a5c3               	LDA	Bpntrl		; get BASIC execute pointer low byte
  4321  a104 48                 	PHA				; push it
  4322  a105 b19c               	LDA	(func_l),Y		; get function execute pointer low byte
  4323  a107 85c3               	STA	Bpntrl		; save as BASIC execute pointer low byte
  4324  a109 c8                 	INY				; index to high byte
  4325  a10a b19c               	LDA	(func_l),Y		; get function execute pointer high byte
  4326  a10c 85c4               	STA	Bpntrh		; save as BASIC execute pointer high byte
  4327  a10e a596               	LDA	Cvarah		; get variable address high byte
  4328  a110 48                 	PHA				; push it
  4329  a111 a595               	LDA	Cvaral		; get variable address low byte
  4330  a113 48                 	PHA				; push it
  4331  a114 20e49a             	JSR	LAB_EVNM		; evaluate expression and check is numeric,
  4332                          					; else do type mismatch
  4333  a117 68                 	PLA				; pull variable address low byte
  4334  a118 859c               	STA	func_l		; save variable address low byte
  4335  a11a 68                 	PLA				; pull variable address high byte
  4336  a11b 859d               	STA	func_h		; save variable address high byte
  4337  a11d 20c200             	JSR	LAB_GBYT		; scan memory
  4338  a120 f003               	BEQ	LAB_2074		; branch if null (should be [EOL] marker)
  4339                          
  4340  a122 4c199c             	JMP	LAB_SNER		; else syntax error then warm start
  4341                          
  4342                          ; restore Bpntrl,Bpntrh and function variable from stack
  4343                          
  4344                          LAB_2074
  4345  a125 68                 	PLA				; pull BASIC execute pointer low byte
  4346  a126 85c3               	STA	Bpntrl		; restore BASIC execute pointer low byte
  4347  a128 68                 	PLA				; pull BASIC execute pointer high byte
  4348  a129 85c4               	STA	Bpntrh		; restore BASIC execute pointer high byte
  4349                          
  4350                          ; put execute pointer and variable pointer into function
  4351                          
  4352                          LAB_207A
  4353  a12b a000               	LDY	#$00			; clear index
  4354  a12d 68                 	PLA				; pull BASIC execute pointer low byte
  4355  a12e 919c               	STA	(func_l),Y		; save to function
  4356  a130 c8                 	INY				; increment index
  4357  a131 68                 	PLA				; pull BASIC execute pointer high byte
  4358  a132 919c               	STA	(func_l),Y		; save to function
  4359  a134 c8                 	INY				; increment index
  4360  a135 68                 	PLA				; pull current var address low byte
  4361  a136 919c               	STA	(func_l),Y		; save to function
  4362  a138 c8                 	INY				; increment index
  4363  a139 68                 	PLA				; pull current var address high byte
  4364  a13a 919c               	STA	(func_l),Y		; save to function
  4365  a13c 60                 	RTS
  4366                          
  4367                          ; perform STR$()
  4368                          
  4369                          LAB_STRS
  4370  a13d 20e79a             	JSR	LAB_CTNM		; check if source is numeric, else do type mismatch
  4371  a140 20acaa             	JSR	LAB_296E		; convert FAC1 to string
  4372  a143 a9e3               	LDA	#<Decssp1		; set result string low pointer
  4373  a145 a000               	LDY	#>Decssp1		; set result string high pointer
  4374  a147 f012               	BEQ	LAB_20AE		; print null terminated string to Sutill/Sutilh
  4375                          
  4376                          ; Do string vector
  4377                          ; copy des_pl/h to des_2l/h and make string space A bytes long
  4378                          
  4379                          LAB_209C
  4380  a149 a6ae               	LDX	des_pl		; get descriptor pointer low byte
  4381  a14b a4af               	LDY	des_ph		; get descriptor pointer high byte
  4382  a14d 869e               	STX	des_2l		; save descriptor pointer low byte
  4383  a14f 849f               	STY	des_2h		; save descriptor pointer high byte
  4384                          
  4385                          ; make string space A bytes long
  4386                          ; A=length, X=Sutill=ptr low byte, Y=Sutilh=ptr high byte
  4387                          
  4388                          LAB_MSSP
  4389  a151 20c4a1             	JSR	LAB_2115		; make space in string memory for string A long
  4390                          					; return X=Sutill=ptr low byte, Y=Sutilh=ptr high byte
  4391  a154 86ad               	STX	str_pl		; save string pointer low byte
  4392  a156 84ae               	STY	str_ph		; save string pointer high byte
  4393  a158 85ac               	STA	str_ln		; save length
  4394  a15a 60                 	RTS
  4395                          
  4396                          ; Scan, set up string
  4397                          ; print " terminated string to Sutill/Sutilh
  4398                          
  4399                          LAB_20AE
  4400  a15b a222               	LDX	#$22			; set terminator to "
  4401  a15d 865b               	STX	Srchc			; set search character (terminator 1)
  4402  a15f 865c               	STX	Asrch			; set terminator 2
  4403                          
  4404                          ; print [Srchc] or [Asrch] terminated string to Sutill/Sutilh
  4405                          ; source is AY
  4406                          
  4407                          LAB_20B4
  4408  a161 85b8               	STA	ssptr_l		; store string start low byte
  4409  a163 84b9               	STY	ssptr_h		; store string start high byte
  4410  a165 85ad               	STA	str_pl		; save string pointer low byte
  4411  a167 84ae               	STY	str_ph		; save string pointer high byte
  4412  a169 a0ff               	LDY	#$FF			; set length to -1
  4413                          LAB_20BE
  4414  a16b c8                 	INY				; increment length
  4415  a16c b1b8               	LDA	(ssptr_l),Y		; get byte from string
  4416  a16e f00c               	BEQ	LAB_20CF		; exit loop if null byte [EOS]
  4417                          
  4418  a170 c55b               	CMP	Srchc			; compare with search character (terminator 1)
  4419  a172 f004               	BEQ	LAB_20CB		; branch if terminator
  4420                          
  4421  a174 c55c               	CMP	Asrch			; compare with terminator 2
  4422  a176 d0f3               	BNE	LAB_20BE		; loop if not terminator 2
  4423                          
  4424                          LAB_20CB
  4425  a178 c922               	CMP	#$22			; compare with "
  4426  a17a f001               	BEQ	LAB_20D0		; branch if " (carry set if = !)
  4427                          
  4428                          LAB_20CF
  4429  a17c 18                 	CLC				; clear carry for add (only if [EOL] terminated string)
  4430                          LAB_20D0
  4431  a17d 84ac               	STY	str_ln		; save length in FAC1 exponent
  4432  a17f 98                 	TYA				; copy length to A
  4433  a180 65b8               	ADC	ssptr_l		; add string start low byte
  4434  a182 85ba               	STA	Sendl			; save string end low byte
  4435  a184 a6b9               	LDX	ssptr_h		; get string start high byte
  4436  a186 9001               	BCC	LAB_20DC		; branch if no low byte overflow
  4437                          
  4438  a188 e8                 	INX				; else increment high byte
  4439                          LAB_20DC
  4440  a189 86bb               	STX	Sendh			; save string end high byte
  4441  a18b a5b9               	LDA	ssptr_h		; get string start high byte
  4442  a18d c904               	CMP	#>Ram_base		; compare with start of program memory
  4443  a18f b00b               	BCS	LAB_RTST		; branch if not in utility area
  4444                          
  4445                          					; string in utility area, move to string memory
  4446  a191 98                 	TYA				; copy length to A
  4447  a192 2049a1             	JSR	LAB_209C		; copy des_pl/h to des_2l/h and make string space A bytes
  4448                          					; long
  4449  a195 a6b8               	LDX	ssptr_l		; get string start low byte
  4450  a197 a4b9               	LDY	ssptr_h		; get string start high byte
  4451  a199 2036a3             	JSR	LAB_2298		; store string A bytes long from XY to (Sutill)
  4452                          
  4453                          ; check for space on descriptor stack then ..
  4454                          ; put string address and length on descriptor stack and update stack pointers
  4455                          
  4456                          LAB_RTST
  4457  a19c a665               	LDX	next_s		; get string stack pointer
  4458  a19e e071               	CPX	#des_sk+$09		; compare with max+1
  4459  a1a0 d005               	BNE	LAB_20F8		; branch if space on string stack
  4460                          
  4461                          					; else do string too complex error
  4462  a1a2 a21c               	LDX	#$1C			; error code $1C ("String too complex" error)
  4463                          LAB_20F5
  4464  a1a4 4c4791             	JMP	LAB_XERR		; do error #X, then warm start
  4465                          
  4466                          ; put string address and length on descriptor stack and update stack pointers
  4467                          
  4468                          LAB_20F8
  4469  a1a7 a5ac               	LDA	str_ln		; get string length
  4470  a1a9 9500               	STA	PLUS_0,X		; put on string stack
  4471  a1ab a5ad               	LDA	str_pl		; get string pointer low byte
  4472  a1ad 9501               	STA	PLUS_1,X		; put on string stack
  4473  a1af a5ae               	LDA	str_ph		; get string pointer high byte
  4474  a1b1 9502               	STA	PLUS_2,X		; put on string stack
  4475  a1b3 a000               	LDY	#$00			; clear Y
  4476  a1b5 86ae               	STX	des_pl		; save string descriptor pointer low byte
  4477  a1b7 84af               	STY	des_ph		; save string descriptor pointer high byte (always $00)
  4478  a1b9 88                 	DEY				; Y = $FF
  4479  a1ba 845f               	STY	Dtypef		; save data type flag, $FF=string
  4480  a1bc 8666               	STX	last_sl		; save old stack pointer (current top item)
  4481  a1be e8                 	INX				; update stack pointer
  4482  a1bf e8                 	INX				; update stack pointer
  4483  a1c0 e8                 	INX				; update stack pointer
  4484  a1c1 8665               	STX	next_s		; save new top item value
  4485  a1c3 60                 	RTS
  4486                          
  4487                          ; Build descriptor
  4488                          ; make space in string memory for string A long
  4489                          ; return X=Sutill=ptr low byte, Y=Sutill=ptr high byte
  4490                          
  4491                          LAB_2115
  4492  a1c4 4660               	LSR	Gclctd		; clear garbage collected flag (b7)
  4493                          
  4494                          					; make space for string A long
  4495                          LAB_2117
  4496  a1c6 48                 	PHA				; save string length
  4497  a1c7 49ff               	EOR	#$FF			; complement it
  4498  a1c9 38                 	SEC				; set carry for subtract (twos comp add)
  4499  a1ca 6581               	ADC	Sstorl		; add bottom of string space low byte (subtract length)
  4500  a1cc a482               	LDY	Sstorh		; get bottom of string space high byte
  4501  a1ce b001               	BCS	LAB_2122		; skip decrement if no underflow
  4502                          
  4503  a1d0 88                 	DEY				; decrement bottom of string space high byte
  4504                          LAB_2122
  4505  a1d1 c480               	CPY	Earryh		; compare with array mem end high byte
  4506  a1d3 9011               	BCC	LAB_2137		; do out of memory error if less
  4507                          
  4508  a1d5 d004               	BNE	LAB_212C		; if not = skip next test
  4509                          
  4510  a1d7 c57f               	CMP	Earryl		; compare with array mem end low byte
  4511  a1d9 900b               	BCC	LAB_2137		; do out of memory error if less
  4512                          
  4513                          LAB_212C
  4514  a1db 8581               	STA	Sstorl		; save bottom of string space low byte
  4515  a1dd 8482               	STY	Sstorh		; save bottom of string space high byte
  4516  a1df 8583               	STA	Sutill		; save string utility ptr low byte
  4517  a1e1 8484               	STY	Sutilh		; save string utility ptr high byte
  4518  a1e3 aa                 	TAX				; copy low byte to X
  4519  a1e4 68                 	PLA				; get string length back
  4520  a1e5 60                 	RTS
  4521                          
  4522                          LAB_2137
  4523  a1e6 a20c               	LDX	#$0C			; error code $0C ("Out of memory" error)
  4524  a1e8 a560               	LDA	Gclctd		; get garbage collected flag
  4525  a1ea 30b8               	BMI	LAB_20F5		; if set then do error code X
  4526                          
  4527  a1ec 20f6a1             	JSR	LAB_GARB		; else go do garbage collection
  4528  a1ef a980               	LDA	#$80			; flag for garbage collected
  4529  a1f1 8560               	STA	Gclctd		; set garbage collected flag
  4530  a1f3 68                 	PLA				; pull length
  4531  a1f4 d0d0               	BNE	LAB_2117		; go try again (loop always, length should never be = $00)
  4532                          
  4533                          ; garbage collection routine
  4534                          
  4535                          LAB_GARB
  4536  a1f6 a685               	LDX	Ememl			; get end of mem low byte
  4537  a1f8 a586               	LDA	Ememh			; get end of mem high byte
  4538                          
  4539                          ; re-run routine from last ending
  4540                          
  4541                          LAB_214B
  4542  a1fa 8681               	STX	Sstorl		; set string storage low byte
  4543  a1fc 8582               	STA	Sstorh		; set string storage high byte
  4544  a1fe a000               	LDY	#$00			; clear index
  4545  a200 849d               	STY	garb_h		; clear working pointer high byte (flag no strings to move)
  4546  a202 a57f               	LDA	Earryl		; get array mem end low byte
  4547  a204 a680               	LDX	Earryh		; get array mem end high byte
  4548  a206 85aa               	STA	Histrl		; save as highest string low byte
  4549  a208 86ab               	STX	Histrh		; save as highest string high byte
  4550  a20a a968               	LDA	#des_sk		; set descriptor stack pointer
  4551  a20c 8571               	STA	ut1_pl		; save descriptor stack pointer low byte
  4552  a20e 8472               	STY	ut1_ph		; save descriptor stack pointer high byte ($00)
  4553                          LAB_2161
  4554  a210 c565               	CMP	next_s		; compare with descriptor stack pointer
  4555  a212 f005               	BEQ	LAB_216A		; branch if =
  4556                          
  4557  a214 207aa2             	JSR	LAB_21D7		; go garbage collect descriptor stack
  4558  a217 f0f7               	BEQ	LAB_2161		; loop always
  4559                          
  4560                          					; done stacked strings, now do string vars
  4561                          LAB_216A
  4562  a219 06a0               	ASL	g_step		; set step size = $06
  4563  a21b a57b               	LDA	Svarl			; get start of vars low byte
  4564  a21d a67c               	LDX	Svarh			; get start of vars high byte
  4565  a21f 8571               	STA	ut1_pl		; save as pointer low byte
  4566  a221 8672               	STX	ut1_ph		; save as pointer high byte
  4567                          LAB_2176
  4568  a223 e47e               	CPX	Sarryh		; compare start of arrays high byte
  4569  a225 d004               	BNE	LAB_217E		; branch if no high byte match
  4570                          
  4571  a227 c57d               	CMP	Sarryl		; else compare start of arrays low byte
  4572  a229 f005               	BEQ	LAB_2183		; branch if = var mem end
  4573                          
  4574                          LAB_217E
  4575  a22b 2074a2             	JSR	LAB_21D1		; go garbage collect strings
  4576  a22e f0f3               	BEQ	LAB_2176		; loop always
  4577                          
  4578                          					; done string vars, now do string arrays
  4579                          LAB_2183
  4580  a230 85a4               	STA	Nbendl		; save start of arrays low byte as working pointer
  4581  a232 86a5               	STX	Nbendh		; save start of arrays high byte as working pointer
  4582  a234 a904               	LDA	#$04			; set step size
  4583  a236 85a0               	STA	g_step		; save step size
  4584                          LAB_218B
  4585  a238 a5a4               	LDA	Nbendl		; get pointer low byte
  4586  a23a a6a5               	LDX	Nbendh		; get pointer high byte
  4587                          LAB_218F
  4588  a23c e480               	CPX	Earryh		; compare with array mem end high byte
  4589  a23e d004               	BNE	LAB_219A		; branch if not at end
  4590                          
  4591  a240 c57f               	CMP	Earryl		; else compare with array mem end low byte
  4592  a242 f075               	BEQ	LAB_2216		; tidy up and exit if at end
  4593                          
  4594                          LAB_219A
  4595  a244 8571               	STA	ut1_pl		; save pointer low byte
  4596  a246 8672               	STX	ut1_ph		; save pointer high byte
  4597  a248 a002               	LDY	#$02			; set index
  4598  a24a b171               	LDA	(ut1_pl),Y		; get array size low byte
  4599  a24c 65a4               	ADC	Nbendl		; add start of this array low byte
  4600  a24e 85a4               	STA	Nbendl		; save start of next array low byte
  4601  a250 c8                 	INY				; increment index
  4602  a251 b171               	LDA	(ut1_pl),Y		; get array size high byte
  4603  a253 65a5               	ADC	Nbendh		; add start of this array high byte
  4604  a255 85a5               	STA	Nbendh		; save start of next array high byte
  4605  a257 a001               	LDY	#$01			; set index
  4606  a259 b171               	LDA	(ut1_pl),Y		; get name second byte
  4607  a25b 10db               	BPL	LAB_218B		; skip if not string array
  4608                          
  4609                          ; was string array so ..
  4610                          
  4611  a25d a004               	LDY	#$04			; set index
  4612  a25f b171               	LDA	(ut1_pl),Y		; get # of dimensions
  4613  a261 0a                 	ASL				; *2
  4614  a262 6905               	ADC	#$05			; +5 (array header size)
  4615  a264 20aca2             	JSR	LAB_2208		; go set up for first element
  4616                          LAB_21C4
  4617  a267 e4a5               	CPX	Nbendh		; compare with start of next array high byte
  4618  a269 d004               	BNE	LAB_21CC		; branch if <> (go do this array)
  4619                          
  4620  a26b c5a4               	CMP	Nbendl		; else compare element pointer low byte with next array
  4621                          					; low byte
  4622  a26d f0cd               	BEQ	LAB_218F		; if equal then go do next array
  4623                          
  4624                          LAB_21CC
  4625  a26f 207aa2             	JSR	LAB_21D7		; go defrag array strings
  4626  a272 f0f3               	BEQ	LAB_21C4		; go do next array string (loop always)
  4627                          
  4628                          ; defrag string variables
  4629                          ; enter with XA = variable pointer
  4630                          ; return with XA = next variable pointer
  4631                          
  4632                          LAB_21D1
  4633  a274 c8                 	INY				; increment index (Y was $00)
  4634  a275 b171               	LDA	(ut1_pl),Y		; get var name byte 2
  4635  a277 1030               	BPL	LAB_2206		; if not string, step pointer to next var and return
  4636                          
  4637  a279 c8                 	INY				; else increment index
  4638                          LAB_21D7
  4639  a27a b171               	LDA	(ut1_pl),Y		; get string length
  4640  a27c f02b               	BEQ	LAB_2206		; if null, step pointer to next string and return
  4641                          
  4642  a27e c8                 	INY				; else increment index
  4643  a27f b171               	LDA	(ut1_pl),Y		; get string pointer low byte
  4644  a281 aa                 	TAX				; copy to X
  4645  a282 c8                 	INY				; increment index
  4646  a283 b171               	LDA	(ut1_pl),Y		; get string pointer high byte
  4647  a285 c582               	CMP	Sstorh		; compare bottom of string space high byte
  4648  a287 9006               	BCC	LAB_21EC		; branch if less
  4649                          
  4650  a289 d01e               	BNE	LAB_2206		; if greater, step pointer to next string and return
  4651                          
  4652                          					; high bytes were = so compare low bytes
  4653  a28b e481               	CPX	Sstorl		; compare bottom of string space low byte
  4654  a28d b01a               	BCS	LAB_2206		; if >=, step pointer to next string and return
  4655                          
  4656                          					; string pointer is < string storage pointer (pos in mem)
  4657                          LAB_21EC
  4658  a28f c5ab               	CMP	Histrh		; compare to highest string high byte
  4659  a291 9017               	BCC	LAB_2207		; if <, step pointer to next string and return
  4660                          
  4661  a293 d004               	BNE	LAB_21F6		; if > update pointers, step to next and return
  4662                          
  4663                          					; high bytes were = so compare low bytes
  4664  a295 e4aa               	CPX	Histrl		; compare to highest string low byte
  4665  a297 9011               	BCC	LAB_2207		; if <, step pointer to next string and return
  4666                          
  4667                          					; string is in string memory space
  4668                          LAB_21F6
  4669  a299 86aa               	STX	Histrl		; save as new highest string low byte
  4670  a29b 85ab               	STA	Histrh		; save as new highest string high byte
  4671  a29d a571               	LDA	ut1_pl		; get start of vars(descriptors) low byte
  4672  a29f a672               	LDX	ut1_ph		; get start of vars(descriptors) high byte
  4673  a2a1 859c               	STA	garb_l		; save as working pointer low byte
  4674  a2a3 869d               	STX	garb_h		; save as working pointer high byte
  4675  a2a5 88                 	DEY				; decrement index DIFFERS
  4676  a2a6 88                 	DEY				; decrement index (should point to descriptor start)
  4677  a2a7 84a2               	STY	g_indx		; save index pointer
  4678                          
  4679                          					; step pointer to next string
  4680                          LAB_2206
  4681  a2a9 18                 	CLC				; clear carry for add
  4682                          LAB_2207
  4683  a2aa a5a0               	LDA	g_step		; get step size
  4684                          LAB_2208
  4685  a2ac 6571               	ADC	ut1_pl		; add pointer low byte
  4686  a2ae 8571               	STA	ut1_pl		; save pointer low byte
  4687  a2b0 9002               	BCC	LAB_2211		; branch if no overflow
  4688                          
  4689  a2b2 e672               	INC	ut1_ph		; else increment high byte
  4690                          LAB_2211
  4691  a2b4 a672               	LDX	ut1_ph		; get pointer high byte
  4692  a2b6 a000               	LDY	#$00			; clear Y
  4693  a2b8 60                 	RTS
  4694                          
  4695                          ; search complete, now either exit or set-up and move string
  4696                          
  4697                          LAB_2216
  4698  a2b9 c6a0               	DEC	g_step		; decrement step size (now $03 for descriptor stack)
  4699  a2bb a69d               	LDX	garb_h		; get string to move high byte
  4700  a2bd f0f5               	BEQ	LAB_2211		; exit if nothing to move
  4701                          
  4702  a2bf a4a2               	LDY	g_indx		; get index byte back (points to descriptor)
  4703  a2c1 18                 	CLC				; clear carry for add
  4704  a2c2 b19c               	LDA	(garb_l),Y		; get string length
  4705  a2c4 65aa               	ADC	Histrl		; add highest string low byte
  4706  a2c6 85a6               	STA	Obendl		; save old block end low pointer
  4707  a2c8 a5ab               	LDA	Histrh		; get highest string high byte
  4708  a2ca 6900               	ADC	#$00			; add any carry
  4709  a2cc 85a7               	STA	Obendh		; save old block end high byte
  4710  a2ce a581               	LDA	Sstorl		; get bottom of string space low byte
  4711  a2d0 a682               	LDX	Sstorh		; get bottom of string space high byte
  4712  a2d2 85a4               	STA	Nbendl		; save new block end low byte
  4713  a2d4 86a5               	STX	Nbendh		; save new block end high byte
  4714  a2d6 20d390             	JSR	LAB_11D6		; open up space in memory, don't set array end
  4715  a2d9 a4a2               	LDY	g_indx		; get index byte
  4716  a2db c8                 	INY				; point to descriptor low byte
  4717  a2dc a5a4               	LDA	Nbendl		; get string pointer low byte
  4718  a2de 919c               	STA	(garb_l),Y		; save new string pointer low byte
  4719  a2e0 aa                 	TAX				; copy string pointer low byte
  4720  a2e1 e6a5               	INC	Nbendh		; correct high byte (move sets high byte -1)
  4721  a2e3 a5a5               	LDA	Nbendh		; get new string pointer high byte
  4722  a2e5 c8                 	INY				; point to descriptor high byte
  4723  a2e6 919c               	STA	(garb_l),Y		; save new string pointer high byte
  4724  a2e8 4cfaa1             	JMP	LAB_214B		; re-run routine from last ending
  4725                          					; (but don't collect this string)
  4726                          
  4727                          ; concatenate
  4728                          ; add strings, string 1 is in descriptor des_pl, string 2 is in line
  4729                          
  4730                          LAB_224D
  4731  a2eb a5af               	LDA	des_ph		; get descriptor pointer high byte
  4732  a2ed 48                 	PHA				; put on stack
  4733  a2ee a5ae               	LDA	des_pl		; get descriptor pointer low byte
  4734  a2f0 48                 	PHA				; put on stack
  4735  a2f1 20e49b             	JSR	LAB_GVAL		; get value from line
  4736  a2f4 20e99a             	JSR	LAB_CTST		; check if source is string, else do type mismatch
  4737  a2f7 68                 	PLA				; get descriptor pointer low byte back
  4738  a2f8 85b8               	STA	ssptr_l		; set pointer low byte
  4739  a2fa 68                 	PLA				; get descriptor pointer high byte back
  4740  a2fb 85b9               	STA	ssptr_h		; set pointer high byte
  4741  a2fd a000               	LDY	#$00			; clear index
  4742  a2ff b1b8               	LDA	(ssptr_l),Y		; get length_1 from descriptor
  4743  a301 18                 	CLC				; clear carry for add
  4744  a302 71ae               	ADC	(des_pl),Y		; add length_2
  4745  a304 9005               	BCC	LAB_226D		; branch if no overflow
  4746                          
  4747  a306 a21a               	LDX	#$1A			; else set error code $1A ("String too long" error)
  4748  a308 4c4791             	JMP	LAB_XERR		; do error #X, then warm start
  4749                          
  4750                          LAB_226D
  4751  a30b 2049a1             	JSR	LAB_209C		; copy des_pl/h to des_2l/h and make string space A bytes
  4752                          					; long
  4753  a30e 2028a3             	JSR	LAB_228A		; copy string from descriptor (sdescr) to (Sutill)
  4754  a311 a59e               	LDA	des_2l		; get descriptor pointer low byte
  4755  a313 a49f               	LDY	des_2h		; get descriptor pointer high byte
  4756  a315 2059a3             	JSR	LAB_22BA		; pop (YA) descriptor off stack or from top of string space
  4757                          					; returns with A = length, ut1_pl = pointer low byte,
  4758                          					; ut1_ph = pointer high byte
  4759  a318 203aa3             	JSR	LAB_229C		; store string A bytes long from (ut1_pl) to (Sutill)
  4760  a31b a5b8               	LDA	ssptr_l		;.set descriptor pointer low byte
  4761  a31d a4b9               	LDY	ssptr_h		;.set descriptor pointer high byte
  4762  a31f 2059a3             	JSR	LAB_22BA		; pop (YA) descriptor off stack or from top of string space
  4763                          					; returns with A = length, X=ut1_pl=pointer low byte,
  4764                          					; Y=ut1_ph=pointer high byte
  4765  a322 209ca1             	JSR	LAB_RTST		; check for space on descriptor stack then put string
  4766                          					; address and length on descriptor stack and update stack
  4767                          					; pointers
  4768  a325 4c0f9b             	JMP	LAB_1ADB		;.continue evaluation
  4769                          
  4770                          ; copy string from descriptor (sdescr) to (Sutill)
  4771                          
  4772                          LAB_228A
  4773  a328 a000               	LDY	#$00			; clear index
  4774  a32a b1b8               	LDA	(sdescr),Y		; get string length
  4775  a32c 48                 	PHA				; save on stack
  4776  a32d c8                 	INY				; increment index
  4777  a32e b1b8               	LDA	(sdescr),Y		; get source string pointer low byte
  4778  a330 aa                 	TAX				; copy to X
  4779  a331 c8                 	INY				; increment index
  4780  a332 b1b8               	LDA	(sdescr),Y		; get source string pointer high byte
  4781  a334 a8                 	TAY				; copy to Y
  4782  a335 68                 	PLA				; get length back
  4783                          
  4784                          ; store string A bytes long from YX to (Sutill)
  4785                          
  4786                          LAB_2298
  4787  a336 8671               	STX	ut1_pl		; save source string pointer low byte
  4788  a338 8472               	STY	ut1_ph		; save source string pointer high byte
  4789                          
  4790                          ; store string A bytes long from (ut1_pl) to (Sutill)
  4791                          
  4792                          LAB_229C
  4793  a33a aa                 	TAX				; copy length to index (don't count with Y)
  4794  a33b f014               	BEQ	LAB_22B2		; branch if = $0 (null string) no need to add zero length
  4795                          
  4796  a33d a000               	LDY	#$00			; zero pointer (copy forward)
  4797                          LAB_22A0
  4798  a33f b171               	LDA	(ut1_pl),Y		; get source byte
  4799  a341 9183               	STA	(Sutill),Y		; save destination byte
  4800                          
  4801  a343 c8                 	INY				; increment index
  4802  a344 ca                 	DEX				; decrement counter
  4803  a345 d0f8               	BNE	LAB_22A0		; loop while <> 0
  4804                          
  4805  a347 98                 	TYA				; restore length from Y
  4806                          LAB_22A9
  4807  a348 18                 	CLC				; clear carry for add
  4808  a349 6583               	ADC	Sutill		; add string utility ptr low byte
  4809  a34b 8583               	STA	Sutill		; save string utility ptr low byte
  4810  a34d 9002               	BCC	LAB_22B2		; branch if no carry
  4811                          
  4812  a34f e684               	INC	Sutilh		; else increment string utility ptr high byte
  4813                          LAB_22B2
  4814  a351 60                 	RTS
  4815                          
  4816                          ; evaluate string
  4817                          
  4818                          LAB_EVST
  4819  a352 20e99a             	JSR	LAB_CTST		; check if source is string, else do type mismatch
  4820                          
  4821                          ; pop string off descriptor stack, or from top of string space
  4822                          ; returns with A = length, X=pointer low byte, Y=pointer high byte
  4823                          
  4824                          LAB_22B6
  4825  a355 a5ae               	LDA	des_pl		; get descriptor pointer low byte
  4826  a357 a4af               	LDY	des_ph		; get descriptor pointer high byte
  4827                          
  4828                          ; pop (YA) descriptor off stack or from top of string space
  4829                          ; returns with A = length, X=ut1_pl=pointer low byte, Y=ut1_ph=pointer high byte
  4830                          
  4831                          LAB_22BA
  4832  a359 8571               	STA	ut1_pl		; save descriptor pointer low byte
  4833  a35b 8472               	STY	ut1_ph		; save descriptor pointer high byte
  4834  a35d 208aa3             	JSR	LAB_22EB		; clean descriptor stack, YA = pointer
  4835  a360 08                 	PHP				; save status flags
  4836  a361 a000               	LDY	#$00			; clear index
  4837  a363 b171               	LDA	(ut1_pl),Y		; get length from string descriptor
  4838  a365 48                 	PHA				; put on stack
  4839  a366 c8                 	INY				; increment index
  4840  a367 b171               	LDA	(ut1_pl),Y		; get string pointer low byte from descriptor
  4841  a369 aa                 	TAX				; copy to X
  4842  a36a c8                 	INY				; increment index
  4843  a36b b171               	LDA	(ut1_pl),Y		; get string pointer high byte from descriptor
  4844  a36d a8                 	TAY				; copy to Y
  4845  a36e 68                 	PLA				; get string length back
  4846  a36f 28                 	PLP				; restore status
  4847  a370 d013               	BNE	LAB_22E6		; branch if pointer <> last_sl,last_sh
  4848                          
  4849  a372 c482               	CPY	Sstorh		; compare bottom of string space high byte
  4850  a374 d00f               	BNE	LAB_22E6		; branch if <>
  4851                          
  4852  a376 e481               	CPX	Sstorl		; else compare bottom of string space low byte
  4853  a378 d00b               	BNE	LAB_22E6		; branch if <>
  4854                          
  4855  a37a 48                 	PHA				; save string length
  4856  a37b 18                 	CLC				; clear carry for add
  4857  a37c 6581               	ADC	Sstorl		; add bottom of string space low byte
  4858  a37e 8581               	STA	Sstorl		; save bottom of string space low byte
  4859  a380 9002               	BCC	LAB_22E5		; skip increment if no overflow
  4860                          
  4861  a382 e682               	INC	Sstorh		; increment bottom of string space high byte
  4862                          LAB_22E5
  4863  a384 68                 	PLA				; restore string length
  4864                          LAB_22E6
  4865  a385 8671               	STX	ut1_pl		; save string pointer low byte
  4866  a387 8472               	STY	ut1_ph		; save string pointer high byte
  4867  a389 60                 	RTS
  4868                          
  4869                          ; clean descriptor stack, YA = pointer
  4870                          ; checks if AY is on the descriptor stack, if so does a stack discard
  4871                          
  4872                          LAB_22EB
  4873  a38a c467               	CPY	last_sh		; compare pointer high byte
  4874  a38c d00c               	BNE	LAB_22FB		; exit if <>
  4875                          
  4876  a38e c566               	CMP	last_sl		; compare pointer low byte
  4877  a390 d008               	BNE	LAB_22FB		; exit if <>
  4878                          
  4879  a392 8565               	STA	next_s		; save descriptor stack pointer
  4880  a394 e903               	SBC	#$03			; -3
  4881  a396 8566               	STA	last_sl		; save low byte -3
  4882  a398 a000               	LDY	#$00			; clear high byte
  4883                          LAB_22FB
  4884  a39a 60                 	RTS
  4885                          
  4886                          ; perform CHR$()
  4887                          
  4888                          LAB_CHRS
  4889  a39b 20a6a4             	JSR	LAB_EVBY		; evaluate byte expression, result in X
  4890  a39e 8a                 	TXA				; copy to A
  4891  a39f 48                 	PHA				; save character
  4892  a3a0 a901               	LDA	#$01			; string is single byte
  4893  a3a2 2051a1             	JSR	LAB_MSSP		; make string space A bytes long A=$AC=length,
  4894                          					; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte
  4895  a3a5 68                 	PLA				; get character back
  4896  a3a6 a000               	LDY	#$00			; clear index
  4897  a3a8 91ad               	STA	(str_pl),Y		; save byte in string (byte IS string!)
  4898  a3aa 4c9ca1             	JMP	LAB_RTST		; check for space on descriptor stack then put string
  4899                          					; address and length on descriptor stack and update stack
  4900                          					; pointers
  4901                          
  4902                          ; perform LEFT$()
  4903                          
  4904                          LAB_LEFT
  4905  a3ad 48                 	PHA				; push byte parameter
  4906  a3ae 200ea4             	JSR	LAB_236F		; pull string data and byte parameter from stack
  4907                          					; return pointer in des_2l/h, byte in A (and X), Y=0
  4908  a3b1 d19e               	CMP	(des_2l),Y		; compare byte parameter with string length
  4909  a3b3 98                 	TYA				; clear A
  4910  a3b4 f009               	BEQ	LAB_2316		; go do string copy (branch always)
  4911                          
  4912                          ; perform RIGHT$()
  4913                          
  4914                          LAB_RIGHT
  4915  a3b6 48                 	PHA				; push byte parameter
  4916  a3b7 200ea4             	JSR	LAB_236F		; pull string data and byte parameter from stack
  4917                          					; return pointer in des_2l/h, byte in A (and X), Y=0
  4918  a3ba 18                 	CLC				; clear carry for add-1
  4919  a3bb f19e               	SBC	(des_2l),Y		; subtract string length
  4920  a3bd 49ff               	EOR	#$FF			; invert it (A=LEN(expression$)-l)
  4921                          
  4922                          LAB_2316
  4923  a3bf 9004               	BCC	LAB_231C		; branch if string length > byte parameter
  4924                          
  4925  a3c1 b19e               	LDA	(des_2l),Y		; else make parameter = length
  4926  a3c3 aa                 	TAX				; copy to byte parameter copy
  4927  a3c4 98                 	TYA				; clear string start offset
  4928                          LAB_231C
  4929  a3c5 48                 	PHA				; save string start offset
  4930                          LAB_231D
  4931  a3c6 8a                 	TXA				; copy byte parameter (or string length if <)
  4932                          LAB_231E
  4933  a3c7 48                 	PHA				; save string length
  4934  a3c8 2051a1             	JSR	LAB_MSSP		; make string space A bytes long A=$AC=length,
  4935                          					; X=$AD=Sutill=ptr low byte, Y=$AE=Sutilh=ptr high byte
  4936  a3cb a59e               	LDA	des_2l		; get descriptor pointer low byte
  4937  a3cd a49f               	LDY	des_2h		; get descriptor pointer high byte
  4938  a3cf 2059a3             	JSR	LAB_22BA		; pop (YA) descriptor off stack or from top of string space
  4939                          					; returns with A = length, X=ut1_pl=pointer low byte,
  4940                          					; Y=ut1_ph=pointer high byte
  4941  a3d2 68                 	PLA				; get string length back
  4942  a3d3 a8                 	TAY				; copy length to Y
  4943  a3d4 68                 	PLA				; get string start offset back
  4944  a3d5 18                 	CLC				; clear carry for add
  4945  a3d6 6571               	ADC	ut1_pl		; add start offset to string start pointer low byte
  4946  a3d8 8571               	STA	ut1_pl		; save string start pointer low byte
  4947  a3da 9002               	BCC	LAB_2335		; branch if no overflow
  4948                          
  4949  a3dc e672               	INC	ut1_ph		; else increment string start pointer high byte
  4950                          LAB_2335
  4951  a3de 98                 	TYA				; copy length to A
  4952  a3df 203aa3             	JSR	LAB_229C		; store string A bytes long from (ut1_pl) to (Sutill)
  4953  a3e2 4c9ca1             	JMP	LAB_RTST		; check for space on descriptor stack then put string
  4954                          					; address and length on descriptor stack and update stack
  4955                          					; pointers
  4956                          
  4957                          ; perform MID$()
  4958                          
  4959                          LAB_MIDS
  4960  a3e5 48                 	PHA				; push byte parameter
  4961  a3e6 a9ff               	LDA	#$FF			; set default length = 255
  4962  a3e8 85af               	STA	mids_l		; save default length
  4963  a3ea 20c200             	JSR	LAB_GBYT		; scan memory
  4964  a3ed c929               	CMP	#')'			; compare with ")"
  4965  a3ef f006               	BEQ	LAB_2358		; branch if = ")" (skip second byte get)
  4966                          
  4967  a3f1 20159c             	JSR	LAB_1C01		; scan for "," , else do syntax error then warm start
  4968  a3f4 20a3a4             	JSR	LAB_GTBY		; get byte parameter (use copy in mids_l)
  4969                          LAB_2358
  4970  a3f7 200ea4             	JSR	LAB_236F		; pull string data and byte parameter from stack
  4971                          					; return pointer in des_2l/h, byte in A (and X), Y=0
  4972  a3fa ca                 	DEX				; decrement start index
  4973  a3fb 8a                 	TXA				; copy to A
  4974  a3fc 48                 	PHA				; save string start offset
  4975  a3fd 18                 	CLC				; clear carry for sub-1
  4976  a3fe a200               	LDX	#$00			; clear output string length
  4977  a400 f19e               	SBC	(des_2l),Y		; subtract string length
  4978  a402 b0c2               	BCS	LAB_231D		; if start>string length go do null string
  4979                          
  4980  a404 49ff               	EOR	#$FF			; complement -length
  4981  a406 c5af               	CMP	mids_l		; compare byte parameter
  4982  a408 90bd               	BCC	LAB_231E		; if length>remaining string go do RIGHT$
  4983                          
  4984  a40a a5af               	LDA	mids_l		; get length byte
  4985  a40c b0b9               	BCS	LAB_231E		; go do string copy (branch always)
  4986                          
  4987                          ; pull string data and byte parameter from stack
  4988                          ; return pointer in des_2l/h, byte in A (and X), Y=0
  4989                          
  4990                          LAB_236F
  4991  a40e 20069c             	JSR	LAB_1BFB		; scan for ")" , else do syntax error then warm start
  4992  a411 68                 	PLA				; pull return address low byte (return address)
  4993  a412 85a2               	STA	Fnxjpl		; save functions jump vector low byte
  4994  a414 68                 	PLA				; pull return address high byte (return address)
  4995  a415 85a3               	STA	Fnxjph		; save functions jump vector high byte
  4996  a417 68                 	PLA				; pull byte parameter
  4997  a418 aa                 	TAX				; copy byte parameter to X
  4998  a419 68                 	PLA				; pull string pointer low byte
  4999  a41a 859e               	STA	des_2l		; save it
  5000  a41c 68                 	PLA				; pull string pointer high byte
  5001  a41d 859f               	STA	des_2h		; save it
  5002  a41f a000               	LDY	#$00			; clear index
  5003  a421 8a                 	TXA				; copy byte parameter
  5004  a422 f079               	BEQ	LAB_23A8		; if null do function call error then warm start
  5005                          
  5006  a424 e6a2               	INC	Fnxjpl		; increment function jump vector low byte
  5007                          					; (JSR pushes return addr-1. this is all very nice
  5008                          					; but will go tits up if either call is on a page
  5009                          					; boundary!)
  5010  a426 6ca200             	JMP	(Fnxjpl)		; in effect, RTS
  5011                          
  5012                          ; perform LCASE$()
  5013                          
  5014                          LAB_LCASE
  5015  a429 2052a3             	JSR	LAB_EVST		; evaluate string
  5016  a42c 85ac               	STA	str_ln		; set string length
  5017  a42e a8                 	TAY				; copy length to Y
  5018  a42f f038               	BEQ	NoString		; branch if null string
  5019                          
  5020  a431 2051a1             	JSR	LAB_MSSP		; make string space A bytes long A=length,
  5021                          					; X=Sutill=ptr low byte, Y=Sutilh=ptr high byte
  5022  a434 86ad               	STX	str_pl		; save string pointer low byte
  5023  a436 84ae               	STY	str_ph		; save string pointer high byte
  5024  a438 a8                 	TAY				; get string length back
  5025                          
  5026                          LC_loop
  5027  a439 88                 	DEY				; decrement index
  5028  a43a b171               	LDA	(ut1_pl),Y		; get byte from string
  5029  a43c 20399e             	JSR	LAB_1D82		; is character "A" to "Z"
  5030  a43f 9002               	BCC	NoUcase		; branch if not upper case alpha
  5031                          
  5032  a441 0920               	ORA	#$20			; convert upper to lower case
  5033                          NoUcase
  5034  a443 9183               	STA	(Sutill),Y		; save byte back to string
  5035  a445 98                 	TYA				; test index
  5036  a446 d0f1               	BNE	LC_loop		; loop if not all done
  5037                          
  5038  a448 f01f               	BEQ	NoString		; tidy up and exit, branch always
  5039                          
  5040                          ; perform UCASE$()
  5041                          
  5042                          LAB_UCASE
  5043  a44a 2052a3             	JSR	LAB_EVST		; evaluate string
  5044  a44d 85ac               	STA	str_ln		; set string length
  5045  a44f a8                 	TAY				; copy length to Y
  5046  a450 f017               	BEQ	NoString		; branch if null string
  5047                          
  5048  a452 2051a1             	JSR	LAB_MSSP		; make string space A bytes long A=length,
  5049                          					; X=Sutill=ptr low byte, Y=Sutilh=ptr high byte
  5050  a455 86ad               	STX	str_pl		; save string pointer low byte
  5051  a457 84ae               	STY	str_ph		; save string pointer high byte
  5052  a459 a8                 	TAY				; get string length back
  5053                          
  5054                          UC_loop
  5055  a45a 88                 	DEY				; decrement index
  5056  a45b b171               	LDA	(ut1_pl),Y		; get byte from string
  5057  a45d 20359e             	JSR	LAB_CASC		; is character "a" to "z" (or "A" to "Z")
  5058  a460 9002               	BCC	NoLcase		; branch if not alpha
  5059                          
  5060  a462 29df               	AND	#$DF			; convert lower to upper case
  5061                          NoLcase
  5062  a464 9183               	STA	(Sutill),Y		; save byte back to string
  5063  a466 98                 	TYA				; test index
  5064  a467 d0f1               	BNE	UC_loop		; loop if not all done
  5065                          
  5066                          NoString
  5067  a469 4c9ca1             	JMP	LAB_RTST		; check for space on descriptor stack then put string
  5068                          					; address and length on descriptor stack and update stack
  5069                          					; pointers
  5070                          
  5071                          ; perform SADD()
  5072                          
  5073                          LAB_SADD
  5074  a46c 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  5075  a46f 20c19d             	JSR	LAB_GVAR		; get var address
  5076                          
  5077  a472 20069c             	JSR	LAB_1BFB		; scan for ")", else do syntax error then warm start
  5078  a475 20e99a             	JSR	LAB_CTST		; check if source is string, else do type mismatch
  5079                          
  5080  a478 a002               	LDY	#$02			; index to string pointer high byte
  5081  a47a b195               	LDA	(Cvaral),Y		; get string pointer high byte
  5082  a47c aa                 	TAX				; copy string pointer high byte to X
  5083  a47d 88                 	DEY				; index to string pointer low byte
  5084  a47e b195               	LDA	(Cvaral),Y		; get string pointer low byte
  5085  a480 a8                 	TAY				; copy string pointer low byte to Y
  5086  a481 8a                 	TXA				; copy string pointer high byte to A
  5087  a482 4c70a0             	JMP	LAB_AYFC		; save and convert integer AY to FAC1 and return
  5088                          
  5089                          ; perform LEN()
  5090                          
  5091                          LAB_LENS
  5092  a485 208ba4             	JSR	LAB_ESGL		; evaluate string, get length in A (and Y)
  5093  a488 4c7da0             	JMP	LAB_1FD0		; convert Y to byte in FAC1 and return
  5094                          
  5095                          ; evaluate string, get length in Y
  5096                          
  5097                          LAB_ESGL
  5098  a48b 2052a3             	JSR	LAB_EVST		; evaluate string
  5099  a48e a8                 	TAY				; copy length to Y
  5100  a48f 60                 	RTS
  5101                          
  5102                          ; perform ASC()
  5103                          
  5104                          LAB_ASC
  5105  a490 208ba4             	JSR	LAB_ESGL		; evaluate string, get length in A (and Y)
  5106  a493 f008               	BEQ	LAB_23A8		; if null do function call error then warm start
  5107                          
  5108  a495 a000               	LDY	#$00			; set index to first character
  5109  a497 b171               	LDA	(ut1_pl),Y		; get byte
  5110  a499 a8                 	TAY				; copy to Y
  5111  a49a 4c7da0             	JMP	LAB_1FD0		; convert Y to byte in FAC1 and return
  5112                          
  5113                          ; do function call error then warm start
  5114                          
  5115                          LAB_23A8
  5116  a49d 4c409f             	JMP	LAB_FCER		; do function call error then warm start
  5117                          
  5118                          ; scan and get byte parameter
  5119                          
  5120                          LAB_SGBY
  5121  a4a0 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  5122                          
  5123                          ; get byte parameter
  5124                          
  5125                          LAB_GTBY
  5126  a4a3 20e49a             	JSR	LAB_EVNM		; evaluate expression and check is numeric,
  5127                          					; else do type mismatch
  5128                          
  5129                          ; evaluate byte expression, result in X
  5130                          
  5131                          LAB_EVBY
  5132  a4a6 20b99e             	JSR	LAB_EVPI		; evaluate integer expression (no check)
  5133                          
  5134  a4a9 a4ae               	LDY	FAC1_2		; get FAC1 mantissa2
  5135  a4ab d0f0               	BNE	LAB_23A8		; if top byte <> 0 do function call error then warm start
  5136                          
  5137  a4ad a6af               	LDX	FAC1_3		; get FAC1 mantissa3
  5138  a4af 4cc200             	JMP	LAB_GBYT		; scan memory and return
  5139                          
  5140                          ; perform VAL()
  5141                          
  5142                          LAB_VAL
  5143  a4b2 208ba4             	JSR	LAB_ESGL		; evaluate string, get length in A (and Y)
  5144  a4b5 d003               	BNE	LAB_23C5		; branch if not null string
  5145                          
  5146                          					; string was null so set result = $00
  5147  a4b7 4c67a6             	JMP	LAB_24F1		; clear FAC1 exponent and sign and return
  5148                          
  5149                          LAB_23C5
  5150  a4ba a6c3               	LDX	Bpntrl		; get BASIC execute pointer low byte
  5151  a4bc a4c4               	LDY	Bpntrh		; get BASIC execute pointer high byte
  5152  a4be 86ba               	STX	Btmpl			; save BASIC execute pointer low byte
  5153  a4c0 84bb               	STY	Btmph			; save BASIC execute pointer high byte
  5154  a4c2 a671               	LDX	ut1_pl		; get string pointer low byte
  5155  a4c4 86c3               	STX	Bpntrl		; save as BASIC execute pointer low byte
  5156  a4c6 18                 	CLC				; clear carry
  5157  a4c7 6571               	ADC	ut1_pl		; add string length
  5158  a4c9 8573               	STA	ut2_pl		; save string end low byte
  5159  a4cb a572               	LDA	ut1_ph		; get string pointer high byte
  5160  a4cd 85c4               	STA	Bpntrh		; save as BASIC execute pointer high byte
  5161  a4cf 6900               	ADC	#$00			; add carry to high byte
  5162  a4d1 8574               	STA	ut2_ph		; save string end high byte
  5163  a4d3 a000               	LDY	#$00			; set index to $00
  5164  a4d5 b173               	LDA	(ut2_pl),Y		; get string end +1 byte
  5165  a4d7 48                 	PHA				; push it
  5166  a4d8 98                 	TYA				; clear A
  5167  a4d9 9173               	STA	(ut2_pl),Y		; terminate string with $00
  5168  a4db 20c200             	JSR	LAB_GBYT		; scan memory
  5169  a4de 20bda9             	JSR	LAB_2887		; get FAC1 from string
  5170  a4e1 68                 	PLA				; restore string end +1 byte
  5171  a4e2 a000               	LDY	#$00			; set index to zero
  5172  a4e4 9173               	STA	(ut2_pl),Y		; put string end byte back
  5173                          
  5174                          ; restore BASIC execute pointer from temp (Btmpl/Btmph)
  5175                          
  5176                          LAB_23F3
  5177  a4e6 a6ba               	LDX	Btmpl			; get BASIC execute pointer low byte back
  5178  a4e8 a4bb               	LDY	Btmph			; get BASIC execute pointer high byte back
  5179  a4ea 86c3               	STX	Bpntrl		; save BASIC execute pointer low byte
  5180  a4ec 84c4               	STY	Bpntrh		; save BASIC execute pointer high byte
  5181  a4ee 60                 	RTS
  5182                          
  5183                          ; get two parameters for POKE or WAIT
  5184                          
  5185                          LAB_GADB
  5186  a4ef 20e49a             	JSR	LAB_EVNM		; evaluate expression and check is numeric,
  5187                          					; else do type mismatch
  5188  a4f2 2008a5             	JSR	LAB_F2FX		; save integer part of FAC1 in temporary integer
  5189                          
  5190                          ; scan for "," and get byte, else do Syntax error then warm start
  5191                          
  5192                          LAB_SCGB
  5193  a4f5 20159c             	JSR	LAB_1C01		; scan for "," , else do syntax error then warm start
  5194  a4f8 a512               	LDA	Itemph		; save temporary integer high byte
  5195  a4fa 48                 	PHA				; on stack
  5196  a4fb a511               	LDA	Itempl		; save temporary integer low byte
  5197  a4fd 48                 	PHA				; on stack
  5198  a4fe 20a3a4             	JSR	LAB_GTBY		; get byte parameter
  5199  a501 68                 	PLA				; pull low byte
  5200  a502 8511               	STA	Itempl		; restore temporary integer low byte
  5201  a504 68                 	PLA				; pull high byte
  5202  a505 8512               	STA	Itemph		; restore temporary integer high byte
  5203  a507 60                 	RTS
  5204                          
  5205                          ; convert float to fixed routine. accepts any value that fits in 24 bits, +ve or
  5206                          ; -ve and converts it into a right truncated integer in Itempl and Itemph
  5207                          
  5208                          ; save unsigned 16 bit integer part of FAC1 in temporary integer
  5209                          
  5210                          LAB_F2FX
  5211  a508 a5ac               	LDA	FAC1_e		; get FAC1 exponent
  5212  a50a c998               	CMP	#$98			; compare with exponent = 2^24
  5213  a50c b08f               	BCS	LAB_23A8		; if >= do function call error then warm start
  5214                          
  5215                          LAB_F2FU
  5216  a50e 2067a9             	JSR	LAB_2831		; convert FAC1 floating-to-fixed
  5217  a511 a5ae               	LDA	FAC1_2		; get FAC1 mantissa2
  5218  a513 a4af               	LDY	FAC1_3		; get FAC1 mantissa3
  5219  a515 8411               	STY	Itempl		; save temporary integer low byte
  5220  a517 8512               	STA	Itemph		; save temporary integer high byte
  5221  a519 60                 	RTS
  5222                          
  5223                          ; perform PEEK()
  5224                          
  5225                          LAB_PEEK
  5226  a51a 2008a5             	JSR	LAB_F2FX		; save integer part of FAC1 in temporary integer
  5227  a51d a200               	LDX	#$00			; clear index
  5228  a51f a111               	LDA	(Itempl,X)		; get byte via temporary integer (addr)
  5229  a521 a8                 	TAY				; copy byte to Y
  5230  a522 4c7da0             	JMP	LAB_1FD0		; convert Y to byte in FAC1 and return
  5231                          
  5232                          ; perform POKE
  5233                          
  5234                          LAB_POKE
  5235  a525 20efa4             	JSR	LAB_GADB		; get two parameters for POKE or WAIT
  5236  a528 8a                 	TXA				; copy byte argument to A
  5237  a529 a200               	LDX	#$00			; clear index
  5238  a52b 8111               	STA	(Itempl,X)		; save byte via temporary integer (addr)
  5239  a52d 60                 	RTS
  5240                          
  5241                          ; perform DEEK()
  5242                          
  5243                          LAB_DEEK
  5244  a52e 2008a5             	JSR	LAB_F2FX		; save integer part of FAC1 in temporary integer
  5245  a531 a200               	LDX	#$00			; clear index
  5246  a533 a111               	LDA	(Itempl,X)		; PEEK low byte
  5247  a535 a8                 	TAY				; copy to Y
  5248  a536 e611               	INC	Itempl		; increment pointer low byte
  5249  a538 d002               	BNE	Deekh			; skip high increment if no rollover
  5250                          
  5251  a53a e612               	INC	Itemph		; increment pointer high byte
  5252                          Deekh
  5253  a53c a111               	LDA	(Itempl,X)		; PEEK high byte
  5254  a53e 4c70a0             	JMP	LAB_AYFC		; save and convert integer AY to FAC1 and return
  5255                          
  5256                          ; perform DOKE
  5257                          
  5258                          LAB_DOKE
  5259  a541 20e49a             	JSR	LAB_EVNM		; evaluate expression and check is numeric,
  5260                          					; else do type mismatch
  5261  a544 2008a5             	JSR	LAB_F2FX		; convert floating-to-fixed
  5262                          
  5263  a547 8497               	STY	Frnxtl		; save pointer low byte (float to fixed returns word in AY)
  5264  a549 8598               	STA	Frnxth		; save pointer high byte
  5265                          
  5266  a54b 20159c             	JSR	LAB_1C01		; scan for "," , else do syntax error then warm start
  5267  a54e 20e49a             	JSR	LAB_EVNM		; evaluate expression and check is numeric,
  5268                          					; else do type mismatch
  5269  a551 2008a5             	JSR	LAB_F2FX		; convert floating-to-fixed
  5270                          
  5271  a554 98                 	TYA				; copy value low byte (float to fixed returns word in AY)
  5272  a555 a200               	LDX	#$00			; clear index
  5273  a557 8197               	STA	(Frnxtl,X)		; POKE low byte
  5274  a559 e697               	INC	Frnxtl		; increment pointer low byte
  5275  a55b d002               	BNE	Dokeh			; skip high increment if no rollover
  5276                          
  5277  a55d e698               	INC	Frnxth		; increment pointer high byte
  5278                          Dokeh
  5279  a55f a512               	LDA	Itemph		; get value high byte
  5280  a561 8197               	STA	(Frnxtl,X)		; POKE high byte
  5281  a563 4cc200             	JMP	LAB_GBYT		; scan memory and return
  5282                          
  5283                          ; perform SWAP
  5284                          
  5285                          LAB_SWAP
  5286  a566 20c19d             	JSR	LAB_GVAR		; get var1 address
  5287  a569 8597               	STA	Lvarpl		; save var1 address low byte
  5288  a56b 8498               	STY	Lvarph		; save var1 address high byte
  5289  a56d a55f               	LDA	Dtypef		; get data type flag, $FF=string, $00=numeric
  5290  a56f 48                 	PHA				; save data type flag
  5291                          
  5292  a570 20159c             	JSR	LAB_1C01		; scan for "," , else do syntax error then warm start
  5293  a573 20c19d             	JSR	LAB_GVAR		; get var2 address (pointer in Cvaral/h)
  5294  a576 68                 	PLA				; pull var1 data type flag
  5295  a577 455f               	EOR	Dtypef		; compare with var2 data type
  5296  a579 1010               	BPL	SwapErr		; exit if not both the same type
  5297                          
  5298  a57b a003               	LDY	#$03			; four bytes to swap (either value or descriptor+1)
  5299                          SwapLp
  5300  a57d b197               	LDA	(Lvarpl),Y		; get byte from var1
  5301  a57f aa                 	TAX				; save var1 byte
  5302  a580 b195               	LDA	(Cvaral),Y		; get byte from var2
  5303  a582 9197               	STA	(Lvarpl),Y		; save byte to var1
  5304  a584 8a                 	TXA				; restore var1 byte
  5305  a585 9195               	STA	(Cvaral),Y		; save byte to var2
  5306  a587 88                 	DEY				; decrement index
  5307  a588 10f3               	BPL	SwapLp		; loop until done
  5308                          
  5309  a58a 60                 	RTS
  5310                          
  5311                          SwapErr
  5312  a58b 4cf39a             	JMP	LAB_1ABC		; do "Type mismatch" error then warm start
  5313                          
  5314                          ; perform CALL
  5315                          
  5316                          LAB_CALL
  5317  a58e 20e49a             	JSR	LAB_EVNM		; evaluate expression and check is numeric,
  5318                          					; else do type mismatch
  5319  a591 2008a5             	JSR	LAB_F2FX		; convert floating-to-fixed
  5320  a594 a9a5               	LDA	#>CallExit		; set return address high byte
  5321  a596 48                 	PHA				; put on stack
  5322  a597 a99c               	LDA	#<CallExit-1	; set return address low byte
  5323  a599 48                 	PHA				; put on stack
  5324  a59a 6c1100             	JMP	(Itempl)		; do indirect jump to user routine
  5325                          
  5326                          ; if the called routine exits correctly then it will return to here. this will then get
  5327                          ; the next byte for the interpreter and return
  5328                          
  5329                          CallExit
  5330  a59d 4cc200             	JMP	LAB_GBYT		; scan memory and return
  5331                          
  5332                          ; perform WAIT
  5333                          
  5334                          LAB_WAIT
  5335  a5a0 20efa4             	JSR	LAB_GADB		; get two parameters for POKE or WAIT
  5336  a5a3 8697               	STX	Frnxtl		; save byte
  5337  a5a5 a200               	LDX	#$00			; clear mask
  5338  a5a7 20c200             	JSR	LAB_GBYT		; scan memory
  5339  a5aa f003               	BEQ	LAB_2441		; skip if no third argument
  5340                          
  5341  a5ac 20f5a4             	JSR	LAB_SCGB		; scan for "," and get byte, else SN error then warm start
  5342                          LAB_2441
  5343  a5af 8698               	STX	Frnxth		; save EOR argument
  5344                          LAB_2445
  5345  a5b1 b111               	LDA	(Itempl),Y		; get byte via temporary integer (addr)
  5346  a5b3 4598               	EOR	Frnxth		; EOR with second argument (mask)
  5347  a5b5 2597               	AND	Frnxtl		; AND with first argument (byte)
  5348  a5b7 f0f8               	BEQ	LAB_2445		; loop if result is zero
  5349                          
  5350                          LAB_244D
  5351  a5b9 60                 	RTS
  5352                          
  5353                          ; perform subtraction, FAC1 from (AY)
  5354                          
  5355                          LAB_2455
  5356  a5ba 20a2a7             	JSR	LAB_264D		; unpack memory (AY) into FAC2
  5357                          
  5358                          ; perform subtraction, FAC1 from FAC2
  5359                          
  5360                          LAB_SUBTRACT
  5361  a5bd a5b0               	LDA	FAC1_s		; get FAC1 sign (b7)
  5362  a5bf 49ff               	EOR	#$FF			; complement it
  5363  a5c1 85b0               	STA	FAC1_s		; save FAC1 sign (b7)
  5364  a5c3 45b7               	EOR	FAC2_s		; EOR with FAC2 sign (b7)
  5365  a5c5 85b8               	STA	FAC_sc		; save sign compare (FAC1 EOR FAC2)
  5366  a5c7 a5ac               	LDA	FAC1_e		; get FAC1 exponent
  5367  a5c9 4cd8a5             	JMP	LAB_ADD		; go add FAC2 to FAC1
  5368                          
  5369                          ; perform addition
  5370                          
  5371                          LAB_2467
  5372  a5cc 20f1a6             	JSR	LAB_257B		; shift FACX A times right (>8 shifts)
  5373  a5cf 904d               	BCC	LAB_24A8		;.go subtract mantissas
  5374                          
  5375                          ; add 0.5 to FAC1
  5376                          
  5377                          LAB_244E
  5378  a5d1 a915               	LDA	#<LAB_2A96		; set 0.5 pointer low byte
  5379  a5d3 a0b2               	LDY	#>LAB_2A96		; set 0.5 pointer high byte
  5380                          
  5381                          ; add (AY) to FAC1
  5382                          
  5383                          LAB_246C
  5384  a5d5 20a2a7             	JSR	LAB_264D		; unpack memory (AY) into FAC2
  5385                          
  5386                          ; add FAC2 to FAC1
  5387                          
  5388                          LAB_ADD
  5389  a5d8 d010               	BNE	LAB_2474		; branch if FAC1 was not zero
  5390                          
  5391                          ; copy FAC2 to FAC1
  5392                          
  5393                          LAB_279B
  5394  a5da a5b7               	LDA	FAC2_s		; get FAC2 sign (b7)
  5395                          
  5396                          ; save FAC1 sign and copy ABS(FAC2) to FAC1
  5397                          
  5398                          LAB_279D
  5399  a5dc 85b0               	STA	FAC1_s		; save FAC1 sign (b7)
  5400  a5de a204               	LDX	#$04			; 4 bytes to copy
  5401                          LAB_27A1
  5402  a5e0 b5b2               	LDA	FAC1_o,X		; get byte from FAC2,X
  5403  a5e2 95ab               	STA	FAC1_e-1,X		; save byte at FAC1,X
  5404  a5e4 ca                 	DEX				; decrement count
  5405  a5e5 d0f9               	BNE	LAB_27A1		; loop if not all done
  5406                          
  5407  a5e7 86b9               	STX	FAC1_r		; clear FAC1 rounding byte
  5408  a5e9 60                 	RTS
  5409                          
  5410                          					; FAC1 is non zero
  5411                          LAB_2474
  5412  a5ea a6b9               	LDX	FAC1_r		; get FAC1 rounding byte
  5413  a5ec 86a3               	STX	FAC2_r		; save as FAC2 rounding byte
  5414  a5ee a2b3               	LDX	#FAC2_e		; set index to FAC2 exponent addr
  5415  a5f0 a5b3               	LDA	FAC2_e		; get FAC2 exponent
  5416                          LAB_247C
  5417  a5f2 a8                 	TAY				; copy exponent
  5418  a5f3 f0c4               	BEQ	LAB_244D		; exit if zero
  5419                          
  5420  a5f5 38                 	SEC				; set carry for subtract
  5421  a5f6 e5ac               	SBC	FAC1_e		; subtract FAC1 exponent
  5422  a5f8 f024               	BEQ	LAB_24A8		; branch if = (go add mantissa)
  5423                          
  5424  a5fa 9012               	BCC	LAB_2498		; branch if <
  5425                          
  5426                          					; FAC2>FAC1
  5427  a5fc 84ac               	STY	FAC1_e		; save FAC1 exponent
  5428  a5fe a4b7               	LDY	FAC2_s		; get FAC2 sign (b7)
  5429  a600 84b0               	STY	FAC1_s		; save FAC1 sign (b7)
  5430  a602 49ff               	EOR	#$FF			; complement A
  5431  a604 6900               	ADC	#$00			; +1 (twos complement, carry is set)
  5432  a606 a000               	LDY	#$00			; clear Y
  5433  a608 84a3               	STY	FAC2_r		; clear FAC2 rounding byte
  5434  a60a a2ac               	LDX	#FAC1_e		; set index to FAC1 exponent addr
  5435  a60c d004               	BNE	LAB_249C		; branch always
  5436                          
  5437                          LAB_2498
  5438  a60e a000               	LDY	#$00			; clear Y
  5439  a610 84b9               	STY	FAC1_r		; clear FAC1 rounding byte
  5440                          LAB_249C
  5441  a612 c9f9               	CMP	#$F9			; compare exponent diff with $F9
  5442  a614 30b6               	BMI	LAB_2467		; branch if range $79-$F8
  5443                          
  5444  a616 a8                 	TAY				; copy exponent difference to Y
  5445  a617 a5b9               	LDA	FAC1_r		; get FAC1 rounding byte
  5446  a619 5601               	LSR	PLUS_1,X		; shift FAC? mantissa1
  5447  a61b 2008a7             	JSR	LAB_2592		; shift FACX Y times right
  5448                          
  5449                          					; exponents are equal now do mantissa subtract
  5450                          LAB_24A8
  5451  a61e 24b8               	BIT	FAC_sc		; test sign compare (FAC1 EOR FAC2)
  5452  a620 104c               	BPL	LAB_24F8		; if = add FAC2 mantissa to FAC1 mantissa and return
  5453                          
  5454  a622 a0ac               	LDY	#FAC1_e		; set index to FAC1 exponent addr
  5455  a624 e0b3               	CPX	#FAC2_e		; compare X to FAC2 exponent addr
  5456  a626 f002               	BEQ	LAB_24B4		; branch if =
  5457                          
  5458  a628 a0b3               	LDY	#FAC2_e		; else set index to FAC2 exponent addr
  5459                          
  5460                          					; subtract smaller from bigger (take sign of bigger)
  5461                          LAB_24B4
  5462  a62a 38                 	SEC				; set carry for subtract
  5463  a62b 49ff               	EOR	#$FF			; ones complement A
  5464  a62d 65a3               	ADC	FAC2_r		; add FAC2 rounding byte
  5465  a62f 85b9               	STA	FAC1_r		; save FAC1 rounding byte
  5466  a631 b90300             	LDA	PLUS_3,Y		; get FACY mantissa3
  5467  a634 f503               	SBC	PLUS_3,X		; subtract FACX mantissa3
  5468  a636 85af               	STA	FAC1_3		; save FAC1 mantissa3
  5469  a638 b90200             	LDA	PLUS_2,Y		; get FACY mantissa2
  5470  a63b f502               	SBC	PLUS_2,X		; subtract FACX mantissa2
  5471  a63d 85ae               	STA	FAC1_2		; save FAC1 mantissa2
  5472  a63f b90100             	LDA	PLUS_1,Y		; get FACY mantissa1
  5473  a642 f501               	SBC	PLUS_1,X		; subtract FACX mantissa1
  5474  a644 85ad               	STA	FAC1_1		; save FAC1 mantissa1
  5475                          
  5476                          ; do ABS and normalise FAC1
  5477                          
  5478                          LAB_24D0
  5479  a646 b003               	BCS	LAB_24D5		; branch if number is +ve
  5480                          
  5481  a648 20ada6             	JSR	LAB_2537		; negate FAC1
  5482                          
  5483                          ; normalise FAC1
  5484                          
  5485                          LAB_24D5
  5486  a64b a000               	LDY	#$00			; clear Y
  5487  a64d 98                 	TYA				; clear A
  5488  a64e 18                 	CLC				; clear carry for add
  5489                          LAB_24D9
  5490  a64f a6ad               	LDX	FAC1_1		; get FAC1 mantissa1
  5491  a651 d03e               	BNE	LAB_251B		; if not zero normalise FAC1
  5492                          
  5493  a653 a6ae               	LDX	FAC1_2		; get FAC1 mantissa2
  5494  a655 86ad               	STX	FAC1_1		; save FAC1 mantissa1
  5495  a657 a6af               	LDX	FAC1_3		; get FAC1 mantissa3
  5496  a659 86ae               	STX	FAC1_2		; save FAC1 mantissa2
  5497  a65b a6b9               	LDX	FAC1_r		; get FAC1 rounding byte
  5498  a65d 86af               	STX	FAC1_3		; save FAC1 mantissa3
  5499  a65f 84b9               	STY	FAC1_r		; clear FAC1 rounding byte
  5500  a661 6908               	ADC	#$08			; add x to exponent offset
  5501  a663 c918               	CMP	#$18			; compare with $18 (max offset, all bits would be =0)
  5502  a665 d0e8               	BNE	LAB_24D9		; loop if not max
  5503                          
  5504                          ; clear FAC1 exponent and sign
  5505                          
  5506                          LAB_24F1
  5507  a667 a900               	LDA	#$00			; clear A
  5508                          LAB_24F3
  5509  a669 85ac               	STA	FAC1_e		; set FAC1 exponent
  5510                          
  5511                          ; save FAC1 sign
  5512                          
  5513                          LAB_24F5
  5514  a66b 85b0               	STA	FAC1_s		; save FAC1 sign (b7)
  5515  a66d 60                 	RTS
  5516                          
  5517                          ; add FAC2 mantissa to FAC1 mantissa
  5518                          
  5519                          LAB_24F8
  5520  a66e 65a3               	ADC	FAC2_r		; add FAC2 rounding byte
  5521  a670 85b9               	STA	FAC1_r		; save FAC1 rounding byte
  5522  a672 a5af               	LDA	FAC1_3		; get FAC1 mantissa3
  5523  a674 65b6               	ADC	FAC2_3		; add FAC2 mantissa3
  5524  a676 85af               	STA	FAC1_3		; save FAC1 mantissa3
  5525  a678 a5ae               	LDA	FAC1_2		; get FAC1 mantissa2
  5526  a67a 65b5               	ADC	FAC2_2		; add FAC2 mantissa2
  5527  a67c 85ae               	STA	FAC1_2		; save FAC1 mantissa2
  5528  a67e a5ad               	LDA	FAC1_1		; get FAC1 mantissa1
  5529  a680 65b4               	ADC	FAC2_1		; add FAC2 mantissa1
  5530  a682 85ad               	STA	FAC1_1		; save FAC1 mantissa1
  5531  a684 b01a               	BCS	LAB_252A		; if carry then normalise FAC1 for C=1
  5532                          
  5533  a686 60                 	RTS				; else just exit
  5534                          
  5535                          LAB_2511
  5536  a687 6901               	ADC	#$01			; add 1 to exponent offset
  5537  a689 06b9               	ASL	FAC1_r		; shift FAC1 rounding byte
  5538  a68b 26af               	ROL	FAC1_3		; shift FAC1 mantissa3
  5539  a68d 26ae               	ROL	FAC1_2		; shift FAC1 mantissa2
  5540  a68f 26ad               	ROL	FAC1_1		; shift FAC1 mantissa1
  5541                          
  5542                          ; normalise FAC1
  5543                          
  5544                          LAB_251B
  5545  a691 10f4               	BPL	LAB_2511		; loop if not normalised
  5546                          
  5547  a693 38                 	SEC				; set carry for subtract
  5548  a694 e5ac               	SBC	FAC1_e		; subtract FAC1 exponent
  5549  a696 b0cf               	BCS	LAB_24F1		; branch if underflow (set result = $0)
  5550                          
  5551  a698 49ff               	EOR	#$FF			; complement exponent
  5552  a69a 6901               	ADC	#$01			; +1 (twos complement)
  5553  a69c 85ac               	STA	FAC1_e		; save FAC1 exponent
  5554                          
  5555                          ; test and normalise FAC1 for C=0/1
  5556                          
  5557                          LAB_2528
  5558  a69e 900c               	BCC	LAB_2536		; exit if no overflow
  5559                          
  5560                          ; normalise FAC1 for C=1
  5561                          
  5562                          LAB_252A
  5563  a6a0 e6ac               	INC	FAC1_e		; increment FAC1 exponent
  5564  a6a2 f036               	BEQ	LAB_2564		; if zero do overflow error and warm start
  5565                          
  5566  a6a4 66ad               	ROR	FAC1_1		; shift FAC1 mantissa1
  5567  a6a6 66ae               	ROR	FAC1_2		; shift FAC1 mantissa2
  5568  a6a8 66af               	ROR	FAC1_3		; shift FAC1 mantissa3
  5569  a6aa 66b9               	ROR	FAC1_r		; shift FAC1 rounding byte
  5570                          LAB_2536
  5571  a6ac 60                 	RTS
  5572                          
  5573                          ; negate FAC1
  5574                          
  5575                          LAB_2537
  5576  a6ad a5b0               	LDA	FAC1_s		; get FAC1 sign (b7)
  5577  a6af 49ff               	EOR	#$FF			; complement it
  5578  a6b1 85b0               	STA	FAC1_s		; save FAC1 sign (b7)
  5579                          
  5580                          ; twos complement FAC1 mantissa
  5581                          
  5582                          LAB_253D
  5583  a6b3 a5ad               	LDA	FAC1_1		; get FAC1 mantissa1
  5584  a6b5 49ff               	EOR	#$FF			; complement it
  5585  a6b7 85ad               	STA	FAC1_1		; save FAC1 mantissa1
  5586  a6b9 a5ae               	LDA	FAC1_2		; get FAC1 mantissa2
  5587  a6bb 49ff               	EOR	#$FF			; complement it
  5588  a6bd 85ae               	STA	FAC1_2		; save FAC1 mantissa2
  5589  a6bf a5af               	LDA	FAC1_3		; get FAC1 mantissa3
  5590  a6c1 49ff               	EOR	#$FF			; complement it
  5591  a6c3 85af               	STA	FAC1_3		; save FAC1 mantissa3
  5592  a6c5 a5b9               	LDA	FAC1_r		; get FAC1 rounding byte
  5593  a6c7 49ff               	EOR	#$FF			; complement it
  5594  a6c9 85b9               	STA	FAC1_r		; save FAC1 rounding byte
  5595  a6cb e6b9               	INC	FAC1_r		; increment FAC1 rounding byte
  5596  a6cd d00a               	BNE	LAB_2563		; exit if no overflow
  5597                          
  5598                          ; increment FAC1 mantissa
  5599                          
  5600                          LAB_2559
  5601  a6cf e6af               	INC	FAC1_3		; increment FAC1 mantissa3
  5602  a6d1 d006               	BNE	LAB_2563		; finished if no rollover
  5603                          
  5604  a6d3 e6ae               	INC	FAC1_2		; increment FAC1 mantissa2
  5605  a6d5 d002               	BNE	LAB_2563		; finished if no rollover
  5606                          
  5607  a6d7 e6ad               	INC	FAC1_1		; increment FAC1 mantissa1
  5608                          LAB_2563
  5609  a6d9 60                 	RTS
  5610                          
  5611                          ; do overflow error (overflow exit)
  5612                          
  5613                          LAB_2564
  5614  a6da a20a               	LDX	#$0A			; error code $0A ("Overflow" error)
  5615  a6dc 4c4791             	JMP	LAB_XERR		; do error #X, then warm start
  5616                          
  5617                          ; shift FCAtemp << A+8 times
  5618                          
  5619                          LAB_2569
  5620  a6df a274               	LDX	#FACt_1-1		; set offset to FACtemp
  5621                          LAB_256B
  5622  a6e1 b403               	LDY	PLUS_3,X		; get FACX mantissa3
  5623  a6e3 84b9               	STY	FAC1_r		; save as FAC1 rounding byte
  5624  a6e5 b402               	LDY	PLUS_2,X		; get FACX mantissa2
  5625  a6e7 9403               	STY	PLUS_3,X		; save FACX mantissa3
  5626  a6e9 b401               	LDY	PLUS_1,X		; get FACX mantissa1
  5627  a6eb 9402               	STY	PLUS_2,X		; save FACX mantissa2
  5628  a6ed a4b2               	LDY	FAC1_o		; get FAC1 overflow byte
  5629  a6ef 9401               	STY	PLUS_1,X		; save FACX mantissa1
  5630                          
  5631                          ; shift FACX -A times right (> 8 shifts)
  5632                          
  5633                          LAB_257B
  5634  a6f1 6908               	ADC	#$08			; add 8 to shift count
  5635  a6f3 30ec               	BMI	LAB_256B		; go do 8 shift if still -ve
  5636                          
  5637  a6f5 f0ea               	BEQ	LAB_256B		; go do 8 shift if zero
  5638                          
  5639  a6f7 e908               	SBC	#$08			; else subtract 8 again
  5640  a6f9 a8                 	TAY				; save count to Y
  5641  a6fa a5b9               	LDA	FAC1_r		; get FAC1 rounding byte
  5642  a6fc b012               	BCS	LAB_259A		;.
  5643                          
  5644                          LAB_2588
  5645  a6fe 1601               	ASL	PLUS_1,X		; shift FACX mantissa1
  5646  a700 9002               	BCC	LAB_258E		; branch if +ve
  5647                          
  5648  a702 f601               	INC	PLUS_1,X		; this sets b7 eventually
  5649                          LAB_258E
  5650  a704 7601               	ROR	PLUS_1,X		; shift FACX mantissa1 (correct for ASL)
  5651  a706 7601               	ROR	PLUS_1,X		; shift FACX mantissa1 (put carry in b7)
  5652                          
  5653                          ; shift FACX Y times right
  5654                          
  5655                          LAB_2592
  5656  a708 7602               	ROR	PLUS_2,X		; shift FACX mantissa2
  5657  a70a 7603               	ROR	PLUS_3,X		; shift FACX mantissa3
  5658  a70c 6a                 	ROR				; shift FACX rounding byte
  5659  a70d c8                 	INY				; increment exponent diff
  5660  a70e d0ee               	BNE	LAB_2588		; branch if range adjust not complete
  5661                          
  5662                          LAB_259A
  5663  a710 18                 	CLC				; just clear it
  5664  a711 60                 	RTS
  5665                          
  5666                          ; perform LOG()
  5667                          
  5668                          LAB_LOG
  5669  a712 2000a9             	JSR	LAB_27CA		; test sign and zero
  5670  a715 f002               	BEQ	LAB_25C4		; if zero do function call error then warm start
  5671                          
  5672  a717 1003               	BPL	LAB_25C7		; skip error if +ve
  5673                          
  5674                          LAB_25C4
  5675  a719 4c409f             	JMP	LAB_FCER		; do function call error then warm start (-ve)
  5676                          
  5677                          LAB_25C7
  5678  a71c a5ac               	LDA	FAC1_e		; get FAC1 exponent
  5679  a71e e97f               	SBC	#$7F			; normalise it
  5680  a720 48                 	PHA				; save it
  5681  a721 a980               	LDA	#$80			; set exponent to zero
  5682  a723 85ac               	STA	FAC1_e		; save FAC1 exponent
  5683  a725 a995               	LDA	#<LAB_25AD		; set 1/root2 pointer low byte
  5684  a727 a0b1               	LDY	#>LAB_25AD		; set 1/root2 pointer high byte
  5685  a729 20d5a5             	JSR	LAB_246C		; add (AY) to FAC1 (1/root2)
  5686  a72c a999               	LDA	#<LAB_25B1		; set root2 pointer low byte
  5687  a72e a0b1               	LDY	#>LAB_25B1		; set root2 pointer high byte
  5688  a730 2018a8             	JSR	LAB_26CA		; convert AY and do (AY)/FAC1 (root2/(x+(1/root2)))
  5689  a733 a90c               	LDA	#<LAB_259C		; set 1 pointer low byte
  5690  a735 a0b2               	LDY	#>LAB_259C		; set 1 pointer high byte
  5691  a737 20baa5             	JSR	LAB_2455		; subtract (AY) from FAC1 ((root2/(x+(1/root2)))-1)
  5692  a73a a988               	LDA	#<LAB_25A0		; set pointer low byte to counter
  5693  a73c a0b1               	LDY	#>LAB_25A0		; set pointer high byte to counter
  5694  a73e 2068ac             	JSR	LAB_2B6E		; ^2 then series evaluation
  5695  a741 a99d               	LDA	#<LAB_25B5		; set -0.5 pointer low byte
  5696  a743 a0b1               	LDY	#>LAB_25B5		; set -0.5 pointer high byte
  5697  a745 20d5a5             	JSR	LAB_246C		; add (AY) to FAC1
  5698  a748 68                 	PLA				; restore FAC1 exponent
  5699  a749 205caa             	JSR	LAB_2912		; evaluate new ASCII digit
  5700  a74c a9a1               	LDA	#<LAB_25B9		; set LOG(2) pointer low byte
  5701  a74e a0b1               	LDY	#>LAB_25B9		; set LOG(2) pointer high byte
  5702                          
  5703                          ; do convert AY, FCA1*(AY)
  5704                          
  5705                          LAB_25FB
  5706  a750 20a2a7             	JSR	LAB_264D		; unpack memory (AY) into FAC2
  5707                          LAB_MULTIPLY
  5708  a753 f04c               	BEQ	LAB_264C		; exit if zero
  5709                          
  5710  a755 20c8a7             	JSR	LAB_2673		; test and adjust accumulators
  5711  a758 a900               	LDA	#$00			; clear A
  5712  a75a 8575               	STA	FACt_1		; clear temp mantissa1
  5713  a75c 8576               	STA	FACt_2		; clear temp mantissa2
  5714  a75e 8577               	STA	FACt_3		; clear temp mantissa3
  5715  a760 a5b9               	LDA	FAC1_r		; get FAC1 rounding byte
  5716  a762 2077a7             	JSR	LAB_2622		; go do shift/add FAC2
  5717  a765 a5af               	LDA	FAC1_3		; get FAC1 mantissa3
  5718  a767 2077a7             	JSR	LAB_2622		; go do shift/add FAC2
  5719  a76a a5ae               	LDA	FAC1_2		; get FAC1 mantissa2
  5720  a76c 2077a7             	JSR	LAB_2622		; go do shift/add FAC2
  5721  a76f a5ad               	LDA	FAC1_1		; get FAC1 mantissa1
  5722  a771 207ca7             	JSR	LAB_2627		; go do shift/add FAC2
  5723  a774 4c85a8             	JMP	LAB_273C		; copy temp to FAC1, normalise and return
  5724                          
  5725                          LAB_2622
  5726  a777 d003               	BNE	LAB_2627		; branch if byte <> zero
  5727                          
  5728  a779 4cdfa6             	JMP	LAB_2569		; shift FCAtemp << A+8 times
  5729                          
  5730                          					; else do shift and add
  5731                          LAB_2627
  5732  a77c 4a                 	LSR				; shift byte
  5733  a77d 0980               	ORA	#$80			; set top bit (mark for 8 times)
  5734                          LAB_262A
  5735  a77f a8                 	TAY				; copy result
  5736  a780 9013               	BCC	LAB_2640		; skip next if bit was zero
  5737                          
  5738  a782 18                 	CLC				; clear carry for add
  5739  a783 a577               	LDA	FACt_3		; get temp mantissa3
  5740  a785 65b6               	ADC	FAC2_3		; add FAC2 mantissa3
  5741  a787 8577               	STA	FACt_3		; save temp mantissa3
  5742  a789 a576               	LDA	FACt_2		; get temp mantissa2
  5743  a78b 65b5               	ADC	FAC2_2		; add FAC2 mantissa2
  5744  a78d 8576               	STA	FACt_2		; save temp mantissa2
  5745  a78f a575               	LDA	FACt_1		; get temp mantissa1
  5746  a791 65b4               	ADC	FAC2_1		; add FAC2 mantissa1
  5747  a793 8575               	STA	FACt_1		; save temp mantissa1
  5748                          LAB_2640
  5749  a795 6675               	ROR	FACt_1		; shift temp mantissa1
  5750  a797 6676               	ROR	FACt_2		; shift temp mantissa2
  5751  a799 6677               	ROR	FACt_3		; shift temp mantissa3
  5752  a79b 66b9               	ROR	FAC1_r		; shift temp rounding byte
  5753  a79d 98                 	TYA				; get byte back
  5754  a79e 4a                 	LSR				; shift byte
  5755  a79f d0de               	BNE	LAB_262A		; loop if all bits not done
  5756                          
  5757                          LAB_264C
  5758  a7a1 60                 	RTS
  5759                          
  5760                          ; unpack memory (AY) into FAC2
  5761                          
  5762                          LAB_264D
  5763  a7a2 8571               	STA	ut1_pl		; save pointer low byte
  5764  a7a4 8472               	STY	ut1_ph		; save pointer high byte
  5765  a7a6 a003               	LDY	#$03			; 4 bytes to get (0-3)
  5766  a7a8 b171               	LDA	(ut1_pl),Y		; get mantissa3
  5767  a7aa 85b6               	STA	FAC2_3		; save FAC2 mantissa3
  5768  a7ac 88                 	DEY				; decrement index
  5769  a7ad b171               	LDA	(ut1_pl),Y		; get mantissa2
  5770  a7af 85b5               	STA	FAC2_2		; save FAC2 mantissa2
  5771  a7b1 88                 	DEY				; decrement index
  5772  a7b2 b171               	LDA	(ut1_pl),Y		; get mantissa1+sign
  5773  a7b4 85b7               	STA	FAC2_s		; save FAC2 sign (b7)
  5774  a7b6 45b0               	EOR	FAC1_s		; EOR with FAC1 sign (b7)
  5775  a7b8 85b8               	STA	FAC_sc		; save sign compare (FAC1 EOR FAC2)
  5776  a7ba a5b7               	LDA	FAC2_s		; recover FAC2 sign (b7)
  5777  a7bc 0980               	ORA	#$80			; set 1xxx xxx (set normal bit)
  5778  a7be 85b4               	STA	FAC2_1		; save FAC2 mantissa1
  5779  a7c0 88                 	DEY				; decrement index
  5780  a7c1 b171               	LDA	(ut1_pl),Y		; get exponent byte
  5781  a7c3 85b3               	STA	FAC2_e		; save FAC2 exponent
  5782  a7c5 a5ac               	LDA	FAC1_e		; get FAC1 exponent
  5783  a7c7 60                 	RTS
  5784                          
  5785                          ; test and adjust accumulators
  5786                          
  5787                          LAB_2673
  5788  a7c8 a5b3               	LDA	FAC2_e		; get FAC2 exponent
  5789                          LAB_2675
  5790  a7ca f01d               	BEQ	LAB_2696		; branch if FAC2 = $00 (handle underflow)
  5791                          
  5792  a7cc 18                 	CLC				; clear carry for add
  5793  a7cd 65ac               	ADC	FAC1_e		; add FAC1 exponent
  5794  a7cf 9004               	BCC	LAB_2680		; branch if sum of exponents <$0100
  5795                          
  5796  a7d1 3031               	BMI	LAB_269B		; do overflow error
  5797                          
  5798  a7d3 18                 	CLC				; clear carry for the add
  5799  a7d4 2c                 	!text	$2C			; makes next line BIT $1410
  5800                          LAB_2680
  5801  a7d5 1012               	BPL	LAB_2696		; if +ve go handle underflow
  5802                          
  5803  a7d7 6980               	ADC	#$80			; adjust exponent
  5804  a7d9 85ac               	STA	FAC1_e		; save FAC1 exponent
  5805  a7db d003               	BNE	LAB_268B		; branch if not zero
  5806                          
  5807  a7dd 4c6ba6             	JMP	LAB_24F5		; save FAC1 sign and return
  5808                          
  5809                          LAB_268B
  5810  a7e0 a5b8               	LDA	FAC_sc		; get sign compare (FAC1 EOR FAC2)
  5811  a7e2 85b0               	STA	FAC1_s		; save FAC1 sign (b7)
  5812                          LAB_268F
  5813  a7e4 60                 	RTS
  5814                          
  5815                          ; handle overflow and underflow
  5816                          
  5817                          LAB_2690
  5818  a7e5 a5b0               	LDA	FAC1_s		; get FAC1 sign (b7)
  5819  a7e7 101b               	BPL	LAB_269B		; do overflow error
  5820                          
  5821                          					; handle underflow
  5822                          LAB_2696
  5823  a7e9 68                 	PLA				; pop return address low byte
  5824  a7ea 68                 	PLA				; pop return address high byte
  5825  a7eb 4c67a6             	JMP	LAB_24F1		; clear FAC1 exponent and sign and return
  5826                          
  5827                          ; multiply by 10
  5828                          
  5829                          LAB_269E
  5830  a7ee 20e1a8             	JSR	LAB_27AB		; round and copy FAC1 to FAC2
  5831  a7f1 aa                 	TAX				; copy exponent (set the flags)
  5832  a7f2 f0f0               	BEQ	LAB_268F		; exit if zero
  5833                          
  5834  a7f4 18                 	CLC				; clear carry for add
  5835  a7f5 6902               	ADC	#$02			; add two to exponent (*4)
  5836  a7f7 b00b               	BCS	LAB_269B		; do overflow error if > $FF
  5837                          
  5838  a7f9 a200               	LDX	#$00			; clear byte
  5839  a7fb 86b8               	STX	FAC_sc		; clear sign compare (FAC1 EOR FAC2)
  5840  a7fd 20f2a5             	JSR	LAB_247C		; add FAC2 to FAC1 (*5)
  5841  a800 e6ac               	INC	FAC1_e		; increment FAC1 exponent (*10)
  5842  a802 d0e0               	BNE	LAB_268F		; if non zero just do RTS
  5843                          
  5844                          LAB_269B
  5845  a804 4cdaa6             	JMP	LAB_2564		; do overflow error and warm start
  5846                          
  5847                          ; divide by 10
  5848                          
  5849                          LAB_26B9
  5850  a807 20e1a8             	JSR	LAB_27AB		; round and copy FAC1 to FAC2
  5851  a80a a91d               	LDA	#<LAB_26B5		; set pointer to 10d low addr
  5852  a80c a0b2               	LDY	#>LAB_26B5		; set pointer to 10d high addr
  5853  a80e a200               	LDX	#$00			; clear sign
  5854                          
  5855                          ; divide by (AY) (X=sign)
  5856                          
  5857                          LAB_26C2
  5858  a810 86b8               	STX	FAC_sc		; save sign compare (FAC1 EOR FAC2)
  5859  a812 2094a8             	JSR	LAB_UFAC		; unpack memory (AY) into FAC1
  5860  a815 4c1ba8             	JMP	LAB_DIVIDE		; do FAC2/FAC1
  5861                          
  5862                          					; Perform divide-by
  5863                          ; convert AY and do (AY)/FAC1
  5864                          
  5865                          LAB_26CA
  5866  a818 20a2a7             	JSR	LAB_264D		; unpack memory (AY) into FAC2
  5867                          
  5868                          					; Perform divide-into
  5869                          LAB_DIVIDE
  5870  a81b f063               	BEQ	LAB_2737		; if zero go do /0 error
  5871                          
  5872  a81d 20f0a8             	JSR	LAB_27BA		; round FAC1
  5873  a820 a900               	LDA	#$00			; clear A
  5874  a822 38                 	SEC				; set carry for subtract
  5875  a823 e5ac               	SBC	FAC1_e		; subtract FAC1 exponent (2s complement)
  5876  a825 85ac               	STA	FAC1_e		; save FAC1 exponent
  5877  a827 20c8a7             	JSR	LAB_2673		; test and adjust accumulators
  5878  a82a e6ac               	INC	FAC1_e		; increment FAC1 exponent
  5879  a82c f0d6               	BEQ	LAB_269B		; if zero do overflow error
  5880                          
  5881  a82e a2ff               	LDX	#$FF			; set index for pre increment
  5882  a830 a901               	LDA	#$01			; set bit to flag byte save
  5883                          LAB_26E4
  5884  a832 a4b4               	LDY	FAC2_1		; get FAC2 mantissa1
  5885  a834 c4ad               	CPY	FAC1_1		; compare FAC1 mantissa1
  5886  a836 d00a               	BNE	LAB_26F4		; branch if <>
  5887                          
  5888  a838 a4b5               	LDY	FAC2_2		; get FAC2 mantissa2
  5889  a83a c4ae               	CPY	FAC1_2		; compare FAC1 mantissa2
  5890  a83c d004               	BNE	LAB_26F4		; branch if <>
  5891                          
  5892  a83e a4b6               	LDY	FAC2_3		; get FAC2 mantissa3
  5893  a840 c4af               	CPY	FAC1_3		; compare FAC1 mantissa3
  5894                          LAB_26F4
  5895  a842 08                 	PHP				; save FAC2-FAC1 compare status
  5896  a843 2a                 	ROL				; shift the result byte
  5897  a844 900e               	BCC	LAB_2702		; if no carry skip the byte save
  5898                          
  5899  a846 a001               	LDY	#$01			; set bit to flag byte save
  5900  a848 e8                 	INX				; else increment the index to FACt
  5901  a849 e002               	CPX	#$02			; compare with the index to FACt_3
  5902  a84b 3004               	BMI	LAB_2701		; if not last byte just go save it
  5903                          
  5904  a84d d028               	BNE	LAB_272B		; if all done go save FAC1 rounding byte, normalise and
  5905                          					; return
  5906                          
  5907  a84f a040               	LDY	#$40			; set bit to flag byte save for the rounding byte
  5908                          LAB_2701
  5909  a851 9575               	STA	FACt_1,X		; write result byte to FACt_1 + index
  5910  a853 98                 	TYA				; copy the next save byte flag
  5911                          LAB_2702
  5912  a854 28                 	PLP				; restore FAC2-FAC1 compare status
  5913  a855 9014               	BCC	LAB_2704		; if FAC2 < FAC1 then skip the subtract
  5914                          
  5915  a857 a8                 	TAY				; save FAC2-FAC1 compare status
  5916  a858 a5b6               	LDA	FAC2_3		; get FAC2 mantissa3
  5917  a85a e5af               	SBC	FAC1_3		; subtract FAC1 mantissa3
  5918  a85c 85b6               	STA	FAC2_3		; save FAC2 mantissa3
  5919  a85e a5b5               	LDA	FAC2_2		; get FAC2 mantissa2
  5920  a860 e5ae               	SBC	FAC1_2		; subtract FAC1 mantissa2
  5921  a862 85b5               	STA	FAC2_2		; save FAC2 mantissa2
  5922  a864 a5b4               	LDA	FAC2_1		; get FAC2 mantissa1
  5923  a866 e5ad               	SBC	FAC1_1		; subtract FAC1 mantissa1
  5924  a868 85b4               	STA	FAC2_1		; save FAC2 mantissa1
  5925  a86a 98                 	TYA				; restore FAC2-FAC1 compare status
  5926                          
  5927                          					; FAC2 = FAC2*2
  5928                          LAB_2704
  5929  a86b 06b6               	ASL	FAC2_3		; shift FAC2 mantissa3
  5930  a86d 26b5               	ROL	FAC2_2		; shift FAC2 mantissa2
  5931  a86f 26b4               	ROL	FAC2_1		; shift FAC2 mantissa1
  5932  a871 b0cf               	BCS	LAB_26F4		; loop with no compare
  5933                          
  5934  a873 30bd               	BMI	LAB_26E4		; loop with compare
  5935                          
  5936  a875 10cb               	BPL	LAB_26F4		; loop always with no compare
  5937                          
  5938                          ; do A<<6, save as FAC1 rounding byte, normalise and return
  5939                          
  5940                          LAB_272B
  5941  a877 4a                 	LSR				; shift b1 - b0 ..
  5942  a878 6a                 	ROR				; ..
  5943  a879 6a                 	ROR				; .. to b7 - b6
  5944  a87a 85b9               	STA	FAC1_r		; save FAC1 rounding byte
  5945  a87c 28                 	PLP				; dump FAC2-FAC1 compare status
  5946  a87d 4c85a8             	JMP	LAB_273C		; copy temp to FAC1, normalise and return
  5947                          
  5948                          ; do "Divide by zero" error
  5949                          
  5950                          LAB_2737
  5951  a880 a214               	LDX	#$14			; error code $14 ("Divide by zero" error)
  5952  a882 4c4791             	JMP	LAB_XERR		; do error #X, then warm start
  5953                          
  5954                          ; copy temp to FAC1 and normalise
  5955                          
  5956                          LAB_273C
  5957  a885 a575               	LDA	FACt_1		; get temp mantissa1
  5958  a887 85ad               	STA	FAC1_1		; save FAC1 mantissa1
  5959  a889 a576               	LDA	FACt_2		; get temp mantissa2
  5960  a88b 85ae               	STA	FAC1_2		; save FAC1 mantissa2
  5961  a88d a577               	LDA	FACt_3		; get temp mantissa3
  5962  a88f 85af               	STA	FAC1_3		; save FAC1 mantissa3
  5963  a891 4c4ba6             	JMP	LAB_24D5		; normalise FAC1 and return
  5964                          
  5965                          ; unpack memory (AY) into FAC1
  5966                          
  5967                          LAB_UFAC
  5968  a894 8571               	STA	ut1_pl		; save pointer low byte
  5969  a896 8472               	STY	ut1_ph		; save pointer high byte
  5970  a898 a003               	LDY	#$03			; 4 bytes to do
  5971  a89a b171               	LDA	(ut1_pl),Y		; get last byte
  5972  a89c 85af               	STA	FAC1_3		; save FAC1 mantissa3
  5973  a89e 88                 	DEY				; decrement index
  5974  a89f b171               	LDA	(ut1_pl),Y		; get last-1 byte
  5975  a8a1 85ae               	STA	FAC1_2		; save FAC1 mantissa2
  5976  a8a3 88                 	DEY				; decrement index
  5977  a8a4 b171               	LDA	(ut1_pl),Y		; get second byte
  5978  a8a6 85b0               	STA	FAC1_s		; save FAC1 sign (b7)
  5979  a8a8 0980               	ORA	#$80			; set 1xxx xxxx (add normal bit)
  5980  a8aa 85ad               	STA	FAC1_1		; save FAC1 mantissa1
  5981  a8ac 88                 	DEY				; decrement index
  5982  a8ad b171               	LDA	(ut1_pl),Y		; get first byte (exponent)
  5983  a8af 85ac               	STA	FAC1_e		; save FAC1 exponent
  5984  a8b1 84b9               	STY	FAC1_r		; clear FAC1 rounding byte
  5985  a8b3 60                 	RTS
  5986                          
  5987                          ; pack FAC1 into Adatal
  5988                          
  5989                          LAB_276E
  5990  a8b4 a2a4               	LDX	#<Adatal		; set pointer low byte
  5991                          LAB_2770
  5992  a8b6 a000               	LDY	#>Adatal		; set pointer high byte
  5993  a8b8 f004               	BEQ	LAB_2778		; pack FAC1 into (XY) and return
  5994                          
  5995                          ; pack FAC1 into (Lvarpl)
  5996                          
  5997                          LAB_PFAC
  5998  a8ba a697               	LDX	Lvarpl		; get destination pointer low byte
  5999  a8bc a498               	LDY	Lvarph		; get destination pointer high byte
  6000                          
  6001                          ; pack FAC1 into (XY)
  6002                          
  6003                          LAB_2778
  6004  a8be 20f0a8             	JSR	LAB_27BA		; round FAC1
  6005  a8c1 8671               	STX	ut1_pl		; save pointer low byte
  6006  a8c3 8472               	STY	ut1_ph		; save pointer high byte
  6007  a8c5 a003               	LDY	#$03			; set index
  6008  a8c7 a5af               	LDA	FAC1_3		; get FAC1 mantissa3
  6009  a8c9 9171               	STA	(ut1_pl),Y		; store in destination
  6010  a8cb 88                 	DEY				; decrement index
  6011  a8cc a5ae               	LDA	FAC1_2		; get FAC1 mantissa2
  6012  a8ce 9171               	STA	(ut1_pl),Y		; store in destination
  6013  a8d0 88                 	DEY				; decrement index
  6014  a8d1 a5b0               	LDA	FAC1_s		; get FAC1 sign (b7)
  6015  a8d3 097f               	ORA	#$7F			; set bits x111 1111
  6016  a8d5 25ad               	AND	FAC1_1		; AND in FAC1 mantissa1
  6017  a8d7 9171               	STA	(ut1_pl),Y		; store in destination
  6018  a8d9 88                 	DEY				; decrement index
  6019  a8da a5ac               	LDA	FAC1_e		; get FAC1 exponent
  6020  a8dc 9171               	STA	(ut1_pl),Y		; store in destination
  6021  a8de 84b9               	STY	FAC1_r		; clear FAC1 rounding byte
  6022  a8e0 60                 	RTS
  6023                          
  6024                          ; round and copy FAC1 to FAC2
  6025                          
  6026                          LAB_27AB
  6027  a8e1 20f0a8             	JSR	LAB_27BA		; round FAC1
  6028                          
  6029                          ; copy FAC1 to FAC2
  6030                          
  6031                          LAB_27AE
  6032  a8e4 a205               	LDX	#$05			; 5 bytes to copy
  6033                          LAB_27B0
  6034  a8e6 b5ab               	LDA	FAC1_e-1,X		; get byte from FAC1,X
  6035  a8e8 95b2               	STA	FAC1_o,X		; save byte at FAC2,X
  6036  a8ea ca                 	DEX				; decrement count
  6037  a8eb d0f9               	BNE	LAB_27B0		; loop if not all done
  6038                          
  6039  a8ed 86b9               	STX	FAC1_r		; clear FAC1 rounding byte
  6040                          LAB_27B9
  6041  a8ef 60                 	RTS
  6042                          
  6043                          ; round FAC1
  6044                          
  6045                          LAB_27BA
  6046  a8f0 a5ac               	LDA	FAC1_e		; get FAC1 exponent
  6047  a8f2 f0fb               	BEQ	LAB_27B9		; exit if zero
  6048                          
  6049  a8f4 06b9               	ASL	FAC1_r		; shift FAC1 rounding byte
  6050  a8f6 90f7               	BCC	LAB_27B9		; exit if no overflow
  6051                          
  6052                          ; round FAC1 (no check)
  6053                          
  6054                          LAB_27C2
  6055  a8f8 20cfa6             	JSR	LAB_2559		; increment FAC1 mantissa
  6056  a8fb d0f2               	BNE	LAB_27B9		; branch if no overflow
  6057                          
  6058  a8fd 4ca0a6             	JMP	LAB_252A		; normalise FAC1 for C=1 and return
  6059                          
  6060                          ; get FAC1 sign
  6061                          ; return A=FF,C=1/-ve A=01,C=0/+ve
  6062                          
  6063                          LAB_27CA
  6064  a900 a5ac               	LDA	FAC1_e		; get FAC1 exponent
  6065  a902 f009               	BEQ	LAB_27D7		; exit if zero (already correct SGN(0)=0)
  6066                          
  6067                          ; return A=FF,C=1/-ve A=01,C=0/+ve
  6068                          ; no = 0 check
  6069                          
  6070                          LAB_27CE
  6071  a904 a5b0               	LDA	FAC1_s		; else get FAC1 sign (b7)
  6072                          
  6073                          ; return A=FF,C=1/-ve A=01,C=0/+ve
  6074                          ; no = 0 check, sign in A
  6075                          
  6076                          LAB_27D0
  6077  a906 2a                 	ROL				; move sign bit to carry
  6078  a907 a9ff               	LDA	#$FF			; set byte for -ve result
  6079  a909 b002               	BCS	LAB_27D7		; return if sign was set (-ve)
  6080                          
  6081  a90b a901               	LDA	#$01			; else set byte for +ve result
  6082                          LAB_27D7
  6083  a90d 60                 	RTS
  6084                          
  6085                          ; perform SGN()
  6086                          
  6087                          LAB_SGN
  6088  a90e 2000a9             	JSR	LAB_27CA		; get FAC1 sign
  6089                          					; return A=$FF/-ve A=$01/+ve
  6090                          ; save A as integer byte
  6091                          
  6092                          LAB_27DB
  6093  a911 85ad               	STA	FAC1_1		; save FAC1 mantissa1
  6094  a913 a900               	LDA	#$00			; clear A
  6095  a915 85ae               	STA	FAC1_2		; clear FAC1 mantissa2
  6096  a917 a288               	LDX	#$88			; set exponent
  6097                          
  6098                          ; set exp=X, clearFAC1 mantissa3 and normalise
  6099                          
  6100                          LAB_27E3
  6101  a919 a5ad               	LDA	FAC1_1		; get FAC1 mantissa1
  6102  a91b 49ff               	EOR	#$FF			; complement it
  6103  a91d 2a                 	ROL				; sign bit into carry
  6104                          
  6105                          ; set exp=X, clearFAC1 mantissa3 and normalise
  6106                          
  6107                          LAB_STFA
  6108  a91e a900               	LDA	#$00			; clear A
  6109  a920 85af               	STA	FAC1_3		; clear FAC1 mantissa3
  6110  a922 86ac               	STX	FAC1_e		; set FAC1 exponent
  6111  a924 85b9               	STA	FAC1_r		; clear FAC1 rounding byte
  6112  a926 85b0               	STA	FAC1_s		; clear FAC1 sign (b7)
  6113  a928 4c46a6             	JMP	LAB_24D0		; do ABS and normalise FAC1
  6114                          
  6115                          ; perform ABS()
  6116                          
  6117                          LAB_ABS
  6118  a92b 46b0               	LSR	FAC1_s		; clear FAC1 sign (put zero in b7)
  6119  a92d 60                 	RTS
  6120                          
  6121                          ; compare FAC1 with (AY)
  6122                          ; returns A=$00 if FAC1 = (AY)
  6123                          ; returns A=$01 if FAC1 > (AY)
  6124                          ; returns A=$FF if FAC1 < (AY)
  6125                          
  6126                          LAB_27F8
  6127  a92e 8573               	STA	ut2_pl		; save pointer low byte
  6128                          LAB_27FA
  6129  a930 8474               	STY	ut2_ph		; save pointer high byte
  6130  a932 a000               	LDY	#$00			; clear index
  6131  a934 b173               	LDA	(ut2_pl),Y		; get exponent
  6132  a936 c8                 	INY				; increment index
  6133  a937 aa                 	TAX				; copy (AY) exponent to X
  6134  a938 f0c6               	BEQ	LAB_27CA		; branch if (AY) exponent=0 and get FAC1 sign
  6135                          					; A=FF,C=1/-ve A=01,C=0/+ve
  6136                          
  6137  a93a b173               	LDA	(ut2_pl),Y		; get (AY) mantissa1 (with sign)
  6138  a93c 45b0               	EOR	FAC1_s		; EOR FAC1 sign (b7)
  6139  a93e 30c4               	BMI	LAB_27CE		; if signs <> do return A=FF,C=1/-ve
  6140                          					; A=01,C=0/+ve and return
  6141                          
  6142  a940 e4ac               	CPX	FAC1_e		; compare (AY) exponent with FAC1 exponent
  6143  a942 d01a               	BNE	LAB_2828		; branch if different
  6144                          
  6145  a944 b173               	LDA	(ut2_pl),Y		; get (AY) mantissa1 (with sign)
  6146  a946 0980               	ORA	#$80			; normalise top bit
  6147  a948 c5ad               	CMP	FAC1_1		; compare with FAC1 mantissa1
  6148  a94a d012               	BNE	LAB_2828		; branch if different
  6149                          
  6150  a94c c8                 	INY				; increment index
  6151  a94d b173               	LDA	(ut2_pl),Y		; get mantissa2
  6152  a94f c5ae               	CMP	FAC1_2		; compare with FAC1 mantissa2
  6153  a951 d00b               	BNE	LAB_2828		; branch if different
  6154                          
  6155  a953 c8                 	INY				; increment index
  6156  a954 a97f               	LDA	#$7F			; set for 1/2 value rounding byte
  6157  a956 c5b9               	CMP	FAC1_r		; compare with FAC1 rounding byte (set carry)
  6158  a958 b173               	LDA	(ut2_pl),Y		; get mantissa3
  6159  a95a e5af               	SBC	FAC1_3		; subtract FAC1 mantissa3
  6160  a95c f028               	BEQ	LAB_2850		; exit if mantissa3 equal
  6161                          
  6162                          ; gets here if number <> FAC1
  6163                          
  6164                          LAB_2828
  6165  a95e a5b0               	LDA	FAC1_s		; get FAC1 sign (b7)
  6166  a960 9002               	BCC	LAB_282E		; branch if FAC1 > (AY)
  6167                          
  6168  a962 49ff               	EOR	#$FF			; else toggle FAC1 sign
  6169                          LAB_282E
  6170  a964 4c06a9             	JMP	LAB_27D0		; return A=FF,C=1/-ve A=01,C=0/+ve
  6171                          
  6172                          ; convert FAC1 floating-to-fixed
  6173                          
  6174                          LAB_2831
  6175  a967 a5ac               	LDA	FAC1_e		; get FAC1 exponent
  6176  a969 f04a               	BEQ	LAB_287F		; if zero go clear FAC1 and return
  6177                          
  6178  a96b 38                 	SEC				; set carry for subtract
  6179  a96c e998               	SBC	#$98			; subtract maximum integer range exponent
  6180  a96e 24b0               	BIT	FAC1_s		; test FAC1 sign (b7)
  6181  a970 1009               	BPL	LAB_2845		; branch if FAC1 +ve
  6182                          
  6183                          					; FAC1 was -ve
  6184  a972 aa                 	TAX				; copy subtracted exponent
  6185  a973 a9ff               	LDA	#$FF			; overflow for -ve number
  6186  a975 85b2               	STA	FAC1_o		; set FAC1 overflow byte
  6187  a977 20b3a6             	JSR	LAB_253D		; twos complement FAC1 mantissa
  6188  a97a 8a                 	TXA				; restore subtracted exponent
  6189                          LAB_2845
  6190  a97b a2ac               	LDX	#FAC1_e		; set index to FAC1
  6191  a97d c9f9               	CMP	#$F9			; compare exponent result
  6192  a97f 1006               	BPL	LAB_2851		; if < 8 shifts shift FAC1 A times right and return
  6193                          
  6194  a981 20f1a6             	JSR	LAB_257B		; shift FAC1 A times right (> 8 shifts)
  6195  a984 84b2               	STY	FAC1_o		; clear FAC1 overflow byte
  6196                          LAB_2850
  6197  a986 60                 	RTS
  6198                          
  6199                          ; shift FAC1 A times right
  6200                          
  6201                          LAB_2851
  6202  a987 a8                 	TAY				; copy shift count
  6203  a988 a5b0               	LDA	FAC1_s		; get FAC1 sign (b7)
  6204  a98a 2980               	AND	#$80			; mask sign bit only (x000 0000)
  6205  a98c 46ad               	LSR	FAC1_1		; shift FAC1 mantissa1
  6206  a98e 05ad               	ORA	FAC1_1		; OR sign in b7 FAC1 mantissa1
  6207  a990 85ad               	STA	FAC1_1		; save FAC1 mantissa1
  6208  a992 2008a7             	JSR	LAB_2592		; shift FAC1 Y times right
  6209  a995 84b2               	STY	FAC1_o		; clear FAC1 overflow byte
  6210  a997 60                 	RTS
  6211                          
  6212                          ; perform INT()
  6213                          
  6214                          LAB_INT
  6215  a998 a5ac               	LDA	FAC1_e		; get FAC1 exponent
  6216  a99a c998               	CMP	#$98			; compare with max int
  6217  a99c b01e               	BCS	LAB_2886		; exit if >= (already int, too big for fractional part!)
  6218                          
  6219  a99e 2067a9             	JSR	LAB_2831		; convert FAC1 floating-to-fixed
  6220  a9a1 84b9               	STY	FAC1_r		; save FAC1 rounding byte
  6221  a9a3 a5b0               	LDA	FAC1_s		; get FAC1 sign (b7)
  6222  a9a5 84b0               	STY	FAC1_s		; save FAC1 sign (b7)
  6223  a9a7 4980               	EOR	#$80			; toggle FAC1 sign
  6224  a9a9 2a                 	ROL				; shift into carry
  6225  a9aa a998               	LDA	#$98			; set new exponent
  6226  a9ac 85ac               	STA	FAC1_e		; save FAC1 exponent
  6227  a9ae a5af               	LDA	FAC1_3		; get FAC1 mantissa3
  6228  a9b0 855b               	STA	Temp3			; save for EXP() function
  6229  a9b2 4c46a6             	JMP	LAB_24D0		; do ABS and normalise FAC1
  6230                          
  6231                          ; clear FAC1 and return
  6232                          
  6233                          LAB_287F
  6234  a9b5 85ad               	STA	FAC1_1		; clear FAC1 mantissa1
  6235  a9b7 85ae               	STA	FAC1_2		; clear FAC1 mantissa2
  6236  a9b9 85af               	STA	FAC1_3		; clear FAC1 mantissa3
  6237  a9bb a8                 	TAY				; clear Y
  6238                          LAB_2886
  6239  a9bc 60                 	RTS
  6240                          
  6241                          ; get FAC1 from string
  6242                          ; this routine now handles hex and binary values from strings
  6243                          ; starting with "$" and "%" respectively
  6244                          
  6245                          LAB_2887
  6246  a9bd a000               	LDY	#$00			; clear Y
  6247  a9bf 845f               	STY	Dtypef		; clear data type flag, $FF=string, $00=numeric
  6248  a9c1 a209               	LDX	#$09			; set index
  6249                          LAB_288B
  6250  a9c3 94a8               	STY	numexp,X		; clear byte
  6251  a9c5 ca                 	DEX				; decrement index
  6252  a9c6 10fb               	BPL	LAB_288B		; loop until numexp to negnum (and FAC1) = $00
  6253                          
  6254  a9c8 907f               	BCC	LAB_28FE		; branch if 1st character numeric
  6255                          
  6256                          ; get FAC1 from string .. first character wasn't numeric
  6257                          
  6258  a9ca c92d               	CMP	#'-'			; else compare with "-"
  6259  a9cc d004               	BNE	LAB_289A		; branch if not "-"
  6260                          
  6261  a9ce 86b1               	STX	negnum		; set flag for -ve number (X = $FF)
  6262  a9d0 f004               	BEQ	LAB_289C		; branch always (go scan and check for hex/bin)
  6263                          
  6264                          ; get FAC1 from string .. first character wasn't numeric or -
  6265                          
  6266                          LAB_289A
  6267  a9d2 c92b               	CMP	#'+'			; else compare with "+"
  6268  a9d4 d005               	BNE	LAB_289D		; branch if not "+" (go check for hex/bin)
  6269                          
  6270                          ; was "+" or "-" to start, so get next character
  6271                          
  6272                          LAB_289C
  6273  a9d6 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  6274  a9d9 906e               	BCC	LAB_28FE		; branch if numeric character
  6275                          
  6276                          ; code here for hex and binary numbers
  6277                          
  6278                          LAB_289D
  6279  a9db c924               	CMP	#'$'			; else compare with "$"
  6280  a9dd d003               	BNE	LAB_NHEX		; branch if not "$"
  6281                          
  6282  a9df 4c85ae             	JMP	LAB_CHEX		; branch if "$"
  6283                          
  6284                          LAB_NHEX
  6285  a9e2 c925               	CMP	#'%'			; else compare with "%"
  6286  a9e4 d008               	BNE	LAB_28A3		; branch if not "%" (continue original code)
  6287                          
  6288  a9e6 4cb3ae             	JMP	LAB_CBIN		; branch if "%"
  6289                          
  6290                          LAB_289E
  6291  a9e9 20bc00             	JSR	LAB_IGBY		; increment and scan memory (ignore + or get next number)
  6292                          LAB_28A1
  6293  a9ec 905b               	BCC	LAB_28FE		; branch if numeric character
  6294                          
  6295                          ; get FAC1 from string .. character wasn't numeric, -, +, hex or binary
  6296                          
  6297                          LAB_28A3
  6298  a9ee c92e               	CMP	#'.'			; else compare with "."
  6299  a9f0 f02e               	BEQ	LAB_28D5		; branch if "."
  6300                          
  6301                          ; get FAC1 from string .. character wasn't numeric, -, + or .
  6302                          
  6303  a9f2 c945               	CMP	#'E'			; else compare with "E"
  6304  a9f4 d030               	BNE	LAB_28DB		; branch if not "E"
  6305                          
  6306                          					; was "E" so evaluate exponential part
  6307  a9f6 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  6308  a9f9 9017               	BCC	LAB_28C7		; branch if numeric character
  6309                          
  6310  a9fb c9b9               	CMP	#TK_MINUS		; else compare with token for -
  6311  a9fd f00e               	BEQ	LAB_28C2		; branch if token for -
  6312                          
  6313  a9ff c92d               	CMP	#'-'			; else compare with "-"
  6314  aa01 f00a               	BEQ	LAB_28C2		; branch if "-"
  6315                          
  6316  aa03 c9b8               	CMP	#TK_PLUS		; else compare with token for +
  6317  aa05 f008               	BEQ	LAB_28C4		; branch if token for +
  6318                          
  6319  aa07 c92b               	CMP	#'+'			; else compare with "+"
  6320  aa09 f004               	BEQ	LAB_28C4		; branch if "+"
  6321                          
  6322  aa0b d007               	BNE	LAB_28C9		; branch always
  6323                          
  6324                          LAB_28C2
  6325  aa0d 66ab               	ROR	expneg		; set exponent -ve flag (C, which=1, into b7)
  6326                          LAB_28C4
  6327  aa0f 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  6328                          LAB_28C7
  6329  aa12 905b               	BCC	LAB_2925		; branch if numeric character
  6330                          
  6331                          LAB_28C9
  6332  aa14 24ab               	BIT	expneg		; test exponent -ve flag
  6333  aa16 100e               	BPL	LAB_28DB		; if +ve go evaluate exponent
  6334                          
  6335                          					; else do exponent = -exponent 
  6336  aa18 a900               	LDA	#$00			; clear result
  6337  aa1a 38                 	SEC				; set carry for subtract
  6338  aa1b e5a9               	SBC	expcnt		; subtract exponent byte
  6339  aa1d 4c28aa             	JMP	LAB_28DD		; go evaluate exponent
  6340                          
  6341                          LAB_28D5
  6342  aa20 66aa               	ROR	numdpf		; set decimal point flag
  6343  aa22 24aa               	BIT	numdpf		; test decimal point flag
  6344  aa24 50c3               	BVC	LAB_289E		; branch if only one decimal point so far
  6345                          
  6346                          					; evaluate exponent
  6347                          LAB_28DB
  6348  aa26 a5a9               	LDA	expcnt		; get exponent count byte
  6349                          LAB_28DD
  6350  aa28 38                 	SEC				; set carry for subtract
  6351  aa29 e5a8               	SBC	numexp		; subtract numerator exponent
  6352  aa2b 85a9               	STA	expcnt		; save exponent count byte
  6353  aa2d f012               	BEQ	LAB_28F6		; branch if no adjustment
  6354                          
  6355  aa2f 1009               	BPL	LAB_28EF		; else if +ve go do FAC1*10^expcnt
  6356                          
  6357                          					; else go do FAC1/10^(0-expcnt)
  6358                          LAB_28E6
  6359  aa31 2007a8             	JSR	LAB_26B9		; divide by 10
  6360  aa34 e6a9               	INC	expcnt		; increment exponent count byte
  6361  aa36 d0f9               	BNE	LAB_28E6		; loop until all done
  6362                          
  6363  aa38 f007               	BEQ	LAB_28F6		; branch always
  6364                          
  6365                          LAB_28EF
  6366  aa3a 20eea7             	JSR	LAB_269E		; multiply by 10
  6367  aa3d c6a9               	DEC	expcnt		; decrement exponent count byte
  6368  aa3f d0f9               	BNE	LAB_28EF		; loop until all done
  6369                          
  6370                          LAB_28F6
  6371  aa41 a5b1               	LDA	negnum		; get -ve flag
  6372  aa43 3001               	BMI	LAB_28FB		; if -ve do - FAC1 and return
  6373                          
  6374  aa45 60                 	RTS
  6375                          
  6376                          ; do - FAC1 and return
  6377                          
  6378                          LAB_28FB
  6379  aa46 4c0bac             	JMP	LAB_GTHAN		; do - FAC1 and return
  6380                          
  6381                          ; do unsigned FAC1*10+number
  6382                          
  6383                          LAB_28FE
  6384  aa49 48                 	PHA				; save character
  6385  aa4a 24aa               	BIT	numdpf		; test decimal point flag
  6386  aa4c 1002               	BPL	LAB_2905		; skip exponent increment if not set
  6387                          
  6388  aa4e e6a8               	INC	numexp		; else increment number exponent
  6389                          LAB_2905
  6390  aa50 20eea7             	JSR	LAB_269E		; multiply FAC1 by 10
  6391  aa53 68                 	PLA				; restore character
  6392  aa54 290f               	AND	#$0F			; convert to binary
  6393  aa56 205caa             	JSR	LAB_2912		; evaluate new ASCII digit
  6394  aa59 4ce9a9             	JMP	LAB_289E		; go do next character
  6395                          
  6396                          ; evaluate new ASCII digit
  6397                          
  6398                          LAB_2912
  6399  aa5c 48                 	PHA				; save digit
  6400  aa5d 20e1a8             	JSR	LAB_27AB		; round and copy FAC1 to FAC2
  6401  aa60 68                 	PLA				; restore digit
  6402  aa61 2011a9             	JSR	LAB_27DB		; save A as integer byte
  6403  aa64 a5b7               	LDA	FAC2_s		; get FAC2 sign (b7)
  6404  aa66 45b0               	EOR	FAC1_s		; toggle with FAC1 sign (b7)
  6405  aa68 85b8               	STA	FAC_sc		; save sign compare (FAC1 EOR FAC2)
  6406  aa6a a6ac               	LDX	FAC1_e		; get FAC1 exponent
  6407  aa6c 4cd8a5             	JMP	LAB_ADD		; add FAC2 to FAC1 and return
  6408                          
  6409                          ; evaluate next character of exponential part of number
  6410                          
  6411                          LAB_2925
  6412  aa6f a5a9               	LDA	expcnt		; get exponent count byte
  6413  aa71 c90a               	CMP	#$0A			; compare with 10 decimal
  6414  aa73 9009               	BCC	LAB_2934		; branch if less
  6415                          
  6416  aa75 a964               	LDA	#$64			; make all -ve exponents = -100 decimal (causes underflow)
  6417  aa77 24ab               	BIT	expneg		; test exponent -ve flag
  6418  aa79 300e               	BMI	LAB_2942		; branch if -ve
  6419                          
  6420  aa7b 4cdaa6             	JMP	LAB_2564		; else do overflow error
  6421                          
  6422                          LAB_2934
  6423  aa7e 0a                 	ASL				; * 2
  6424  aa7f 0a                 	ASL				; * 4
  6425  aa80 65a9               	ADC	expcnt		; * 5
  6426  aa82 0a                 	ASL				; * 10
  6427  aa83 a000               	LDY	#$00			; set index
  6428  aa85 71c3               	ADC	(Bpntrl),Y		; add character (will be $30 too much!)
  6429  aa87 e92f               	SBC	#'0'-1		; convert character to binary
  6430                          LAB_2942
  6431  aa89 85a9               	STA	expcnt		; save exponent count byte
  6432  aa8b 4c0faa             	JMP	LAB_28C4		; go get next character
  6433                          
  6434                          ; print " in line [LINE #]"
  6435                          
  6436                          LAB_2953
  6437  aa8e a942               	LDA	#<LAB_LMSG		; point to " in line " message low byte
  6438  aa90 a0b8               	LDY	#>LAB_LMSG		; point to " in line " message high byte
  6439  aa92 20ea98             	JSR	LAB_18C3		; print null terminated string from memory
  6440                          
  6441                          					; print Basic line #
  6442  aa95 a588               	LDA	Clineh		; get current line high byte
  6443  aa97 a687               	LDX	Clinel		; get current line low byte
  6444                          
  6445                          ; print XA as unsigned integer
  6446                          
  6447                          LAB_295E
  6448  aa99 85ad               	STA	FAC1_1		; save low byte as FAC1 mantissa1
  6449  aa9b 86ae               	STX	FAC1_2		; save high byte as FAC1 mantissa2
  6450  aa9d a290               	LDX	#$90			; set exponent to 16d bits
  6451  aa9f 38                 	SEC				; set integer is +ve flag
  6452  aaa0 201ea9             	JSR	LAB_STFA		; set exp=X, clearFAC1 mantissa3 and normalise
  6453  aaa3 a000               	LDY	#$00			; clear index
  6454  aaa5 98                 	TYA				; clear A
  6455  aaa6 20b9aa             	JSR	LAB_297B		; convert FAC1 to string, skip sign character save
  6456  aaa9 4cea98             	JMP	LAB_18C3		; print null terminated string from memory and return
  6457                          
  6458                          ; convert FAC1 to ASCII string result in (AY)
  6459                          ; not any more, moved scratchpad to page 0
  6460                          
  6461                          LAB_296E
  6462  aaac a001               	LDY	#$01			; set index = 1
  6463  aaae a920               	LDA	#$20			; character = " " (assume +ve)
  6464  aab0 24b0               	BIT	FAC1_s		; test FAC1 sign (b7)
  6465  aab2 1002               	BPL	LAB_2978		; branch if +ve
  6466                          
  6467  aab4 a92d               	LDA	#$2D			; else character = "-"
  6468                          LAB_2978
  6469  aab6 99e200             	STA	Decss,Y		; save leading character (" " or "-")
  6470                          LAB_297B
  6471  aab9 85b0               	STA	FAC1_s		; clear FAC1 sign (b7)
  6472  aabb 84ba               	STY	Sendl			; save index
  6473  aabd c8                 	INY				; increment index
  6474  aabe a6ac               	LDX	FAC1_e		; get FAC1 exponent
  6475  aac0 d005               	BNE	LAB_2989		; branch if FAC1<>0
  6476                          
  6477                          					; exponent was $00 so FAC1 is 0
  6478  aac2 a930               	LDA	#'0'			; set character = "0"
  6479  aac4 4cc5ab             	JMP	LAB_2A89		; save last character, [EOT] and exit
  6480                          
  6481                          					; FAC1 is some non zero value
  6482                          LAB_2989
  6483  aac7 a900               	LDA	#$00			; clear (number exponent count)
  6484  aac9 e081               	CPX	#$81			; compare FAC1 exponent with $81 (>1.00000)
  6485                          
  6486  aacb b009               	BCS	LAB_299A		; branch if FAC1=>1
  6487                          
  6488                          					; FAC1<1
  6489  aacd a9ad               	LDA	#<LAB_294F		; set pointer low byte to 1,000,000
  6490  aacf a0b1               	LDY	#>LAB_294F		; set pointer high byte to 1,000,000
  6491  aad1 2050a7             	JSR	LAB_25FB		; do convert AY, FCA1*(AY)
  6492  aad4 a9fa               	LDA	#$FA			; set number exponent count (-6)
  6493                          LAB_299A
  6494  aad6 85a8               	STA	numexp		; save number exponent count
  6495                          LAB_299C
  6496  aad8 a9a9               	LDA	#<LAB_294B		; set pointer low byte to 999999.4375 (max before sci note)
  6497  aada a0b1               	LDY	#>LAB_294B		; set pointer high byte to 999999.4375
  6498  aadc 202ea9             	JSR	LAB_27F8		; compare FAC1 with (AY)
  6499  aadf f01e               	BEQ	LAB_29C3		; exit if FAC1 = (AY)
  6500                          
  6501  aae1 1012               	BPL	LAB_29B9		; go do /10 if FAC1 > (AY)
  6502                          
  6503                          					; FAC1 < (AY)
  6504                          LAB_29A7
  6505  aae3 a9a5               	LDA	#<LAB_2947		; set pointer low byte to 99999.9375
  6506  aae5 a0b1               	LDY	#>LAB_2947		; set pointer high byte to 99999.9375
  6507  aae7 202ea9             	JSR	LAB_27F8		; compare FAC1 with (AY)
  6508  aaea f002               	BEQ	LAB_29B2		; branch if FAC1 = (AY) (allow decimal places)
  6509                          
  6510  aaec 100e               	BPL	LAB_29C0		; branch if FAC1 > (AY) (no decimal places)
  6511                          
  6512                          					; FAC1 <= (AY)
  6513                          LAB_29B2
  6514  aaee 20eea7             	JSR	LAB_269E		; multiply by 10
  6515  aaf1 c6a8               	DEC	numexp		; decrement number exponent count
  6516  aaf3 d0ee               	BNE	LAB_29A7		; go test again (branch always)
  6517                          
  6518                          LAB_29B9
  6519  aaf5 2007a8             	JSR	LAB_26B9		; divide by 10
  6520  aaf8 e6a8               	INC	numexp		; increment number exponent count
  6521  aafa d0dc               	BNE	LAB_299C		; go test again (branch always)
  6522                          
  6523                          ; now we have just the digits to do
  6524                          
  6525                          LAB_29C0
  6526  aafc 20d1a5             	JSR	LAB_244E		; add 0.5 to FAC1 (round FAC1)
  6527                          LAB_29C3
  6528  aaff 2067a9             	JSR	LAB_2831		; convert FAC1 floating-to-fixed
  6529  ab02 a201               	LDX	#$01			; set default digits before dp = 1
  6530  ab04 a5a8               	LDA	numexp		; get number exponent count
  6531  ab06 18                 	CLC				; clear carry for add
  6532  ab07 6907               	ADC	#$07			; up to 6 digits before point
  6533  ab09 3009               	BMI	LAB_29D8		; if -ve then 1 digit before dp
  6534                          
  6535  ab0b c908               	CMP	#$08			; A>=8 if n>=1E6
  6536  ab0d b006               	BCS	LAB_29D9		; branch if >= $08
  6537                          
  6538                          					; carry is clear
  6539  ab0f 69ff               	ADC	#$FF			; take 1 from digit count
  6540  ab11 aa                 	TAX				; copy to A
  6541  ab12 a902               	LDA	#$02			;.set exponent adjust
  6542                          LAB_29D8
  6543  ab14 38                 	SEC				; set carry for subtract
  6544                          LAB_29D9
  6545  ab15 e902               	SBC	#$02			; -2
  6546  ab17 85a9               	STA	expcnt		;.save exponent adjust
  6547  ab19 86a8               	STX	numexp		; save digits before dp count
  6548  ab1b 8a                 	TXA				; copy to A
  6549  ab1c f002               	BEQ	LAB_29E4		; branch if no digits before dp
  6550                          
  6551  ab1e 1013               	BPL	LAB_29F7		; branch if digits before dp
  6552                          
  6553                          LAB_29E4
  6554  ab20 a4ba               	LDY	Sendl			; get output string index
  6555  ab22 a92e               	LDA	#$2E			; character "."
  6556  ab24 c8                 	INY				; increment index
  6557  ab25 99e200             	STA	Decss,Y		; save to output string
  6558  ab28 8a                 	TXA				;.
  6559  ab29 f006               	BEQ	LAB_29F5		;.
  6560                          
  6561  ab2b a930               	LDA	#'0'			; character "0"
  6562  ab2d c8                 	INY				; increment index
  6563  ab2e 99e200             	STA	Decss,Y		; save to output string
  6564                          LAB_29F5
  6565  ab31 84ba               	STY	Sendl			; save output string index
  6566                          LAB_29F7
  6567  ab33 a000               	LDY	#$00			; clear index (point to 100,000)
  6568  ab35 a280               	LDX	#$80			; 
  6569                          LAB_29FB
  6570  ab37 a5af               	LDA	FAC1_3		; get FAC1 mantissa3
  6571  ab39 18                 	CLC				; clear carry for add
  6572  ab3a 7923b2             	ADC	LAB_2A9C,Y		; add -ve LSB
  6573  ab3d 85af               	STA	FAC1_3		; save FAC1 mantissa3
  6574  ab3f a5ae               	LDA	FAC1_2		; get FAC1 mantissa2
  6575  ab41 7922b2             	ADC	LAB_2A9B,Y		; add -ve NMSB
  6576  ab44 85ae               	STA	FAC1_2		; save FAC1 mantissa2
  6577  ab46 a5ad               	LDA	FAC1_1		; get FAC1 mantissa1
  6578  ab48 7921b2             	ADC	LAB_2A9A,Y		; add -ve MSB
  6579  ab4b 85ad               	STA	FAC1_1		; save FAC1 mantissa1
  6580  ab4d e8                 	INX				; 
  6581  ab4e b004               	BCS	LAB_2A18		; 
  6582                          
  6583  ab50 10e5               	BPL	LAB_29FB		; not -ve so try again
  6584                          
  6585  ab52 3002               	BMI	LAB_2A1A		; 
  6586                          
  6587                          LAB_2A18
  6588  ab54 30e1               	BMI	LAB_29FB		; 
  6589                          
  6590                          LAB_2A1A
  6591  ab56 8a                 	TXA				; 
  6592  ab57 9004               	BCC	LAB_2A21		; 
  6593                          
  6594  ab59 49ff               	EOR	#$FF			; 
  6595  ab5b 690a               	ADC	#$0A			; 
  6596                          LAB_2A21
  6597  ab5d 692f               	ADC	#'0'-1		; add "0"-1 to result
  6598  ab5f c8                 	INY				; increment index ..
  6599  ab60 c8                 	INY				; .. to next less ..
  6600  ab61 c8                 	INY				; .. power of ten
  6601  ab62 8495               	STY	Cvaral		; save as current var address low byte
  6602  ab64 a4ba               	LDY	Sendl			; get output string index
  6603  ab66 c8                 	INY				; increment output string index
  6604  ab67 aa                 	TAX				; copy character to X
  6605  ab68 297f               	AND	#$7F			; mask out top bit
  6606  ab6a 99e200             	STA	Decss,Y		; save to output string
  6607  ab6d c6a8               	DEC	numexp		; decrement # of characters before the dp
  6608  ab6f d006               	BNE	LAB_2A3B		; branch if still characters to do
  6609                          
  6610                          					; else output the point
  6611  ab71 a92e               	LDA	#$2E			; character "."
  6612  ab73 c8                 	INY				; increment output string index
  6613  ab74 99e200             	STA	Decss,Y		; save to output string
  6614                          LAB_2A3B
  6615  ab77 84ba               	STY	Sendl			; save output string index
  6616  ab79 a495               	LDY	Cvaral		; get current var address low byte
  6617  ab7b 8a                 	TXA				; get character back
  6618  ab7c 49ff               	EOR	#$FF			; 
  6619  ab7e 2980               	AND	#$80			; 
  6620  ab80 aa                 	TAX				; 
  6621  ab81 c012               	CPY	#$12			; compare index with max
  6622  ab83 d0b2               	BNE	LAB_29FB		; loop if not max
  6623                          
  6624                          					; now remove trailing zeroes
  6625  ab85 a4ba               	LDY	Sendl			; get output string index
  6626                          LAB_2A4B
  6627  ab87 b9e200             	LDA	Decss,Y		; get character from output string
  6628  ab8a 88                 	DEY				; decrement output string index
  6629  ab8b c930               	CMP	#'0'			; compare with "0"
  6630  ab8d f0f8               	BEQ	LAB_2A4B		; loop until non "0" character found
  6631                          
  6632  ab8f c92e               	CMP	#'.'			; compare with "."
  6633  ab91 f001               	BEQ	LAB_2A58		; branch if was dp
  6634                          
  6635                          					; restore last character
  6636  ab93 c8                 	INY				; increment output string index
  6637                          LAB_2A58
  6638  ab94 a92b               	LDA	#$2B			; character "+"
  6639  ab96 a6a9               	LDX	expcnt		; get exponent count
  6640  ab98 f02e               	BEQ	LAB_2A8C		; if zero go set null terminator and exit
  6641                          
  6642                          					; exponent isn't zero so write exponent
  6643  ab9a 1008               	BPL	LAB_2A68		; branch if exponent count +ve
  6644                          
  6645  ab9c a900               	LDA	#$00			; clear A
  6646  ab9e 38                 	SEC				; set carry for subtract
  6647  ab9f e5a9               	SBC	expcnt		; subtract exponent count adjust (convert -ve to +ve)
  6648  aba1 aa                 	TAX				; copy exponent count to X
  6649  aba2 a92d               	LDA	#'-'			; character "-"
  6650                          LAB_2A68
  6651  aba4 99e400             	STA	Decss+2,Y		; save to output string
  6652  aba7 a945               	LDA	#$45			; character "E"
  6653  aba9 99e300             	STA	Decss+1,Y		; save exponent sign to output string
  6654  abac 8a                 	TXA				; get exponent count back
  6655  abad a22f               	LDX	#'0'-1		; one less than "0" character
  6656  abaf 38                 	SEC				; set carry for subtract
  6657                          LAB_2A74
  6658  abb0 e8                 	INX				; increment 10's character
  6659  abb1 e90a               	SBC	#$0A			;.subtract 10 from exponent count
  6660  abb3 b0fb               	BCS	LAB_2A74		; loop while still >= 0
  6661                          
  6662  abb5 693a               	ADC	#':'			; add character ":" ($30+$0A, result is 10 less that value)
  6663  abb7 99e600             	STA	Decss+4,Y		; save to output string
  6664  abba 8a                 	TXA				; copy 10's character
  6665  abbb 99e500             	STA	Decss+3,Y		; save to output string
  6666  abbe a900               	LDA	#$00			; set null terminator
  6667  abc0 99e700             	STA	Decss+5,Y		; save to output string
  6668  abc3 f008               	BEQ	LAB_2A91		; go set string pointer (AY) and exit (branch always)
  6669                          
  6670                          					; save last character, [EOT] and exit
  6671                          LAB_2A89
  6672  abc5 99e200             	STA	Decss,Y		; save last character to output string
  6673                          
  6674                          					; set null terminator and exit
  6675                          LAB_2A8C
  6676  abc8 a900               	LDA	#$00			; set null terminator
  6677  abca 99e300             	STA	Decss+1,Y		; save after last character
  6678                          
  6679                          					; set string pointer (AY) and exit
  6680                          LAB_2A91
  6681  abcd a9e3               	LDA	#<Decssp1		; set result string low pointer
  6682  abcf a000               	LDY	#>Decssp1		; set result string high pointer
  6683  abd1 60                 	RTS
  6684                          
  6685                          ; perform power function
  6686                          
  6687                          LAB_POWER
  6688  abd2 f042               	BEQ	LAB_EXP		; go do  EXP()
  6689                          
  6690  abd4 a5b3               	LDA	FAC2_e		; get FAC2 exponent
  6691  abd6 d003               	BNE	LAB_2ABF		; branch if FAC2<>0
  6692                          
  6693  abd8 4c69a6             	JMP	LAB_24F3		; clear FAC1 exponent and sign and return
  6694                          
  6695                          LAB_2ABF
  6696  abdb a29c               	LDX	#<func_l		; set destination pointer low byte
  6697  abdd a000               	LDY	#>func_l		; set destination pointer high byte
  6698  abdf 20bea8             	JSR	LAB_2778		; pack FAC1 into (XY)
  6699  abe2 a5b7               	LDA	FAC2_s		; get FAC2 sign (b7)
  6700  abe4 100f               	BPL	LAB_2AD9		; branch if FAC2>0
  6701                          
  6702                          					; else FAC2 is -ve and can only be raised to an
  6703                          					; integer power which gives an x +j0 result
  6704  abe6 2098a9             	JSR	LAB_INT		; perform INT
  6705  abe9 a99c               	LDA	#<func_l		; set source pointer low byte
  6706  abeb a000               	LDY	#>func_l		; set source pointer high byte
  6707  abed 202ea9             	JSR	LAB_27F8		; compare FAC1 with (AY)
  6708  abf0 d003               	BNE	LAB_2AD9		; branch if FAC1 <> (AY) to allow Function Call error
  6709                          					; this will leave FAC1 -ve and cause a Function Call
  6710                          					; error when LOG() is called
  6711                          
  6712  abf2 98                 	TYA				; clear sign b7
  6713  abf3 a45b               	LDY	Temp3			; save mantissa 3 from INT() function as sign in Y
  6714                          					; for possible later negation, b0
  6715                          LAB_2AD9
  6716  abf5 20dca5             	JSR	LAB_279D		; save FAC1 sign and copy ABS(FAC2) to FAC1
  6717  abf8 98                 	TYA				; copy sign back ..
  6718  abf9 48                 	PHA				; .. and save it
  6719  abfa 2012a7             	JSR	LAB_LOG		; do LOG(n)
  6720  abfd a99c               	LDA	#<garb_l		; set pointer low byte
  6721  abff a000               	LDY	#>garb_l		; set pointer high byte
  6722  ac01 2050a7             	JSR	LAB_25FB		; do convert AY, FCA1*(AY) (square the value)
  6723  ac04 2016ac             	JSR	LAB_EXP		; go do EXP(n)
  6724  ac07 68                 	PLA				; pull sign from stack
  6725  ac08 4a                 	LSR				; b0 is to be tested, shift to Cb
  6726  ac09 900a               	BCC	LAB_2AF9		; if no bit then exit
  6727                          
  6728                          					; Perform negation
  6729                          ; do - FAC1
  6730                          
  6731                          LAB_GTHAN
  6732  ac0b a5ac               	LDA	FAC1_e		; get FAC1 exponent
  6733  ac0d f006               	BEQ	LAB_2AF9		; exit if FAC1_e = $00
  6734                          
  6735  ac0f a5b0               	LDA	FAC1_s		; get FAC1 sign (b7)
  6736  ac11 49ff               	EOR	#$FF			; complement it
  6737  ac13 85b0               	STA	FAC1_s		; save FAC1 sign (b7)
  6738                          LAB_2AF9
  6739  ac15 60                 	RTS
  6740                          
  6741                          ; perform EXP()	(x^e)
  6742                          
  6743                          LAB_EXP
  6744  ac16 a9b1               	LDA	#<LAB_2AFA		; set 1.443 pointer low byte
  6745  ac18 a0b1               	LDY	#>LAB_2AFA		; set 1.443 pointer high byte
  6746  ac1a 2050a7             	JSR	LAB_25FB		; do convert AY, FCA1*(AY)
  6747  ac1d a5b9               	LDA	FAC1_r		; get FAC1 rounding byte
  6748  ac1f 6950               	ADC	#$50			; +$50/$100
  6749  ac21 9003               	BCC	LAB_2B2B		; skip rounding if no carry
  6750                          
  6751  ac23 20f8a8             	JSR	LAB_27C2		; round FAC1 (no check)
  6752                          LAB_2B2B
  6753  ac26 85a3               	STA	FAC2_r		; save FAC2 rounding byte
  6754  ac28 20e4a8             	JSR	LAB_27AE		; copy FAC1 to FAC2
  6755  ac2b a5ac               	LDA	FAC1_e		; get FAC1 exponent
  6756  ac2d c988               	CMP	#$88			; compare with EXP limit (256d)
  6757  ac2f 9003               	BCC	LAB_2B39		; branch if less
  6758                          
  6759                          LAB_2B36
  6760  ac31 20e5a7             	JSR	LAB_2690		; handle overflow and underflow
  6761                          LAB_2B39
  6762  ac34 2098a9             	JSR	LAB_INT		; perform INT
  6763  ac37 a55b               	LDA	Temp3			; get mantissa 3 from INT() function
  6764  ac39 18                 	CLC				; clear carry for add
  6765  ac3a 6981               	ADC	#$81			; normalise +1
  6766  ac3c f0f3               	BEQ	LAB_2B36		; if $00 go handle overflow
  6767                          
  6768  ac3e 38                 	SEC				; set carry for subtract
  6769  ac3f e901               	SBC	#$01			; now correct for exponent
  6770  ac41 48                 	PHA				; save FAC2 exponent
  6771                          
  6772                          					; swap FAC1 and FAC2
  6773  ac42 a204               	LDX	#$04			; 4 bytes to do
  6774                          LAB_2B49
  6775  ac44 b5b3               	LDA	FAC2_e,X		; get FAC2,X
  6776  ac46 b4ac               	LDY	FAC1_e,X		; get FAC1,X
  6777  ac48 95ac               	STA	FAC1_e,X		; save FAC1,X
  6778  ac4a 94b3               	STY	FAC2_e,X		; save FAC2,X
  6779  ac4c ca                 	DEX				; decrement count/index
  6780  ac4d 10f5               	BPL	LAB_2B49		; loop if not all done
  6781                          
  6782  ac4f a5a3               	LDA	FAC2_r		; get FAC2 rounding byte
  6783  ac51 85b9               	STA	FAC1_r		; save as FAC1 rounding byte
  6784  ac53 20bda5             	JSR	LAB_SUBTRACT	; perform subtraction, FAC2 from FAC1
  6785  ac56 200bac             	JSR	LAB_GTHAN		; do - FAC1
  6786  ac59 a9b5               	LDA	#<LAB_2AFE		; set counter pointer low byte
  6787  ac5b a0b1               	LDY	#>LAB_2AFE		; set counter pointer high byte
  6788  ac5d 207eac             	JSR	LAB_2B84		; go do series evaluation
  6789  ac60 a900               	LDA	#$00			; clear A
  6790  ac62 85b8               	STA	FAC_sc		; clear sign compare (FAC1 EOR FAC2)
  6791  ac64 68                 	PLA				;.get saved FAC2 exponent
  6792  ac65 4ccaa7             	JMP	LAB_2675		; test and adjust accumulators and return
  6793                          
  6794                          ; ^2 then series evaluation
  6795                          
  6796                          LAB_2B6E
  6797  ac68 85ba               	STA	Cptrl			; save count pointer low byte
  6798  ac6a 84bb               	STY	Cptrh			; save count pointer high byte
  6799  ac6c 20b4a8             	JSR	LAB_276E		; pack FAC1 into Adatal
  6800  ac6f a9a4               	LDA	#<Adatal		; set pointer low byte (Y already $00)
  6801  ac71 2050a7             	JSR	LAB_25FB		; do convert AY, FCA1*(AY)
  6802  ac74 2082ac             	JSR	LAB_2B88		; go do series evaluation
  6803  ac77 a9a4               	LDA	#<Adatal		; pointer to original # low byte
  6804  ac79 a000               	LDY	#>Adatal		; pointer to original # high byte
  6805  ac7b 4c50a7             	JMP	LAB_25FB		; do convert AY, FCA1*(AY) and return
  6806                          
  6807                          ; series evaluation
  6808                          
  6809                          LAB_2B84
  6810  ac7e 85ba               	STA	Cptrl			; save count pointer low byte
  6811  ac80 84bb               	STY	Cptrh			; save count pointer high byte
  6812                          LAB_2B88
  6813  ac82 a2a8               	LDX	#<numexp		; set pointer low byte
  6814  ac84 20b6a8             	JSR	LAB_2770		; set pointer high byte and pack FAC1 into numexp
  6815  ac87 b1ba               	LDA	(Cptrl),Y		; get constants count
  6816  ac89 85b1               	STA	numcon		; save constants count
  6817  ac8b a4ba               	LDY	Cptrl			; get count pointer low byte
  6818  ac8d c8                 	INY				; increment it (now constants pointer)
  6819  ac8e 98                 	TYA				; copy it
  6820  ac8f d002               	BNE	LAB_2B97		; skip next if no overflow
  6821                          
  6822  ac91 e6bb               	INC	Cptrh			; else increment high byte
  6823                          LAB_2B97
  6824  ac93 85ba               	STA	Cptrl			; save low byte
  6825  ac95 a4bb               	LDY	Cptrh			; get high byte
  6826                          LAB_2B9B
  6827  ac97 2050a7             	JSR	LAB_25FB		; do convert AY, FCA1*(AY)
  6828  ac9a a5ba               	LDA	Cptrl			; get constants pointer low byte
  6829  ac9c a4bb               	LDY	Cptrh			; get constants pointer high byte
  6830  ac9e 18                 	CLC				; clear carry for add
  6831  ac9f 6904               	ADC	#$04			; +4 to  low pointer (4 bytes per constant)
  6832  aca1 9001               	BCC	LAB_2BA8		; skip next if no overflow
  6833                          
  6834  aca3 c8                 	INY				; increment high byte
  6835                          LAB_2BA8
  6836  aca4 85ba               	STA	Cptrl			; save pointer low byte
  6837  aca6 84bb               	STY	Cptrh			; save pointer high byte
  6838  aca8 20d5a5             	JSR	LAB_246C		; add (AY) to FAC1
  6839  acab a9a8               	LDA	#<numexp		; set pointer low byte to partial @ numexp
  6840  acad a000               	LDY	#>numexp		; set pointer high byte to partial @ numexp
  6841  acaf c6b1               	DEC	numcon		; decrement constants count
  6842  acb1 d0e4               	BNE	LAB_2B9B		; loop until all done
  6843                          
  6844  acb3 60                 	RTS
  6845                          
  6846                          ; RND(n), 32 bit Galoise version. make n=0 for 19th next number in sequence or n<>0
  6847                          ; to get 19th next number in sequence after seed n. This version of the PRNG uses
  6848                          ; the Galois method and a sample of 65536 bytes produced gives the following values.
  6849                          
  6850                          ; Entropy = 7.997442 bits per byte
  6851                          ; Optimum compression would reduce these 65536 bytes by 0 percent
  6852                          
  6853                          ; Chi square distribution for 65536 samples is 232.01, and
  6854                          ; randomly would exceed this value 75.00 percent of the time
  6855                          
  6856                          ; Arithmetic mean value of data bytes is 127.6724, 127.5 would be random
  6857                          ; Monte Carlo value for Pi is 3.122871269, error 0.60 percent
  6858                          ; Serial correlation coefficient is -0.000370, totally uncorrelated would be 0.0
  6859                          
  6860                          LAB_RND
  6861  acb4 a5ac               	LDA	FAC1_e		; get FAC1 exponent
  6862  acb6 f007               	BEQ	NextPRN		; do next random # if zero
  6863                          
  6864                          					; else get seed into random number store
  6865  acb8 a2d8               	LDX	#Rbyte4		; set PRNG pointer low byte
  6866  acba a000               	LDY	#$00			; set PRNG pointer high byte
  6867  acbc 20bea8             	JSR	LAB_2778		; pack FAC1 into (XY)
  6868                          NextPRN
  6869  acbf a2af               	LDX	#$AF			; set EOR byte
  6870  acc1 a013               	LDY	#$13			; do this nineteen times
  6871                          LoopPRN
  6872  acc3 06d9               	ASL	Rbyte1		; shift PRNG most significant byte
  6873  acc5 26da               	ROL	Rbyte2		; shift PRNG middle byte
  6874  acc7 26db               	ROL	Rbyte3		; shift PRNG least significant byte
  6875  acc9 26d8               	ROL	Rbyte4		; shift PRNG extra byte
  6876  accb 9005               	BCC	Ninc1			; branch if bit 32 clear
  6877                          
  6878  accd 8a                 	TXA				; set EOR byte
  6879  acce 45d9               	EOR	Rbyte1		; EOR PRNG extra byte
  6880  acd0 85d9               	STA	Rbyte1		; save new PRNG extra byte
  6881                          Ninc1
  6882  acd2 88                 	DEY				; decrement loop count
  6883  acd3 d0ee               	BNE	LoopPRN		; loop if not all done
  6884                          
  6885  acd5 a202               	LDX	#$02			; three bytes to copy
  6886                          CopyPRNG
  6887  acd7 b5d9               	LDA	Rbyte1,X		; get PRNG byte
  6888  acd9 95ad               	STA	FAC1_1,X		; save FAC1 byte
  6889  acdb ca                 	DEX
  6890  acdc 10f9               	BPL	CopyPRNG		; loop if not complete
  6891                          
  6892  acde a980               	LDA	#$80			; set the exponent
  6893  ace0 85ac               	STA	FAC1_e		; save FAC1 exponent
  6894                          
  6895  ace2 0a                 	ASL				; clear A
  6896  ace3 85b0               	STA	FAC1_s		; save FAC1 sign
  6897                          
  6898  ace5 4c4ba6             	JMP	LAB_24D5		; normalise FAC1 and return
  6899                          
  6900                          ; perform COS()
  6901                          
  6902                          LAB_COS
  6903  ace8 a9d2               	LDA	#<LAB_2C78		; set (pi/2) pointer low byte
  6904  acea a0b1               	LDY	#>LAB_2C78		; set (pi/2) pointer high byte
  6905  acec 20d5a5             	JSR	LAB_246C		; add (AY) to FAC1
  6906                          
  6907                          ; perform SIN()
  6908                          
  6909                          LAB_SIN
  6910  acef 20e1a8             	JSR	LAB_27AB		; round and copy FAC1 to FAC2
  6911  acf2 a9e7               	LDA	#<LAB_2C7C		; set (2*pi) pointer low byte
  6912  acf4 a0b1               	LDY	#>LAB_2C7C		; set (2*pi) pointer high byte
  6913  acf6 a6b7               	LDX	FAC2_s		; get FAC2 sign (b7)
  6914  acf8 2010a8             	JSR	LAB_26C2		; divide by (AY) (X=sign)
  6915  acfb 20e1a8             	JSR	LAB_27AB		; round and copy FAC1 to FAC2
  6916  acfe 2098a9             	JSR	LAB_INT		; perform INT
  6917  ad01 a900               	LDA	#$00			; clear byte
  6918  ad03 85b8               	STA	FAC_sc		; clear sign compare (FAC1 EOR FAC2)
  6919  ad05 20bda5             	JSR	LAB_SUBTRACT	; perform subtraction, FAC2 from FAC1
  6920  ad08 a919               	LDA	#<LAB_2C80		; set 0.25 pointer low byte
  6921  ad0a a0b2               	LDY	#>LAB_2C80		; set 0.25 pointer high byte
  6922  ad0c 20baa5             	JSR	LAB_2455		; perform subtraction, (AY) from FAC1
  6923  ad0f a5b0               	LDA	FAC1_s		; get FAC1 sign (b7)
  6924  ad11 48                 	PHA				; save FAC1 sign
  6925  ad12 100d               	BPL	LAB_2C35		; branch if +ve
  6926                          
  6927                          					; FAC1 sign was -ve
  6928  ad14 20d1a5             	JSR	LAB_244E		; add 0.5 to FAC1
  6929  ad17 a5b0               	LDA	FAC1_s		; get FAC1 sign (b7)
  6930  ad19 3009               	BMI	LAB_2C38		; branch if -ve
  6931                          
  6932  ad1b a563               	LDA	Cflag			; get comparison evaluation flag
  6933  ad1d 49ff               	EOR	#$FF			; toggle flag
  6934  ad1f 8563               	STA	Cflag			; save comparison evaluation flag
  6935                          LAB_2C35
  6936  ad21 200bac             	JSR	LAB_GTHAN		; do - FAC1
  6937                          LAB_2C38
  6938  ad24 a919               	LDA	#<LAB_2C80		; set 0.25 pointer low byte
  6939  ad26 a0b2               	LDY	#>LAB_2C80		; set 0.25 pointer high byte
  6940  ad28 20d5a5             	JSR	LAB_246C		; add (AY) to FAC1
  6941  ad2b 68                 	PLA				; restore FAC1 sign
  6942  ad2c 1003               	BPL	LAB_2C45		; branch if was +ve
  6943                          
  6944                          					; else correct FAC1
  6945  ad2e 200bac             	JSR	LAB_GTHAN		; do - FAC1
  6946                          LAB_2C45
  6947  ad31 a9d6               	LDA	#<LAB_2C84		; set pointer low byte to counter
  6948  ad33 a0b1               	LDY	#>LAB_2C84		; set pointer high byte to counter
  6949  ad35 4c68ac             	JMP	LAB_2B6E		; ^2 then series evaluation and return
  6950                          
  6951                          ; perform TAN()
  6952                          
  6953                          LAB_TAN
  6954  ad38 20b4a8             	JSR	LAB_276E		; pack FAC1 into Adatal
  6955  ad3b a900               	LDA	#$00			; clear byte
  6956  ad3d 8563               	STA	Cflag			; clear comparison evaluation flag
  6957  ad3f 20efac             	JSR	LAB_SIN		; go do SIN(n)
  6958  ad42 a29c               	LDX	#<func_l		; set sin(n) pointer low byte
  6959  ad44 a000               	LDY	#>func_l		; set sin(n) pointer high byte
  6960  ad46 20bea8             	JSR	LAB_2778		; pack FAC1 into (XY)
  6961  ad49 a9a4               	LDA	#<Adatal		; set n pointer low addr
  6962  ad4b a000               	LDY	#>Adatal		; set n pointer high addr
  6963  ad4d 2094a8             	JSR	LAB_UFAC		; unpack memory (AY) into FAC1
  6964  ad50 a900               	LDA	#$00			; clear byte
  6965  ad52 85b0               	STA	FAC1_s		; clear FAC1 sign (b7)
  6966  ad54 a563               	LDA	Cflag			; get comparison evaluation flag
  6967  ad56 2060ad             	JSR	LAB_2C74		; save flag and go do series evaluation
  6968                          
  6969  ad59 a99c               	LDA	#<func_l		; set sin(n) pointer low byte
  6970  ad5b a000               	LDY	#>func_l		; set sin(n) pointer high byte
  6971  ad5d 4c18a8             	JMP	LAB_26CA		; convert AY and do (AY)/FAC1
  6972                          
  6973                          LAB_2C74
  6974  ad60 48                 	PHA				; save comparison evaluation flag
  6975  ad61 4c21ad             	JMP	LAB_2C35		; go do series evaluation
  6976                          
  6977                          ; perform USR()
  6978                          
  6979                          LAB_USR
  6980  ad64 200a00             	JSR	Usrjmp		; call user code
  6981  ad67 4c069c             	JMP	LAB_1BFB		; scan for ")", else do syntax error then warm start
  6982                          
  6983                          ; perform ATN()
  6984                          
  6985                          LAB_ATN
  6986  ad6a a5b0               	LDA	FAC1_s		; get FAC1 sign (b7)
  6987  ad6c 48                 	PHA				; save sign
  6988  ad6d 1003               	BPL	LAB_2CA1		; branch if +ve
  6989                          
  6990  ad6f 200bac             	JSR	LAB_GTHAN		; else do - FAC1
  6991                          LAB_2CA1
  6992  ad72 a5ac               	LDA	FAC1_e		; get FAC1 exponent
  6993  ad74 48                 	PHA				; push exponent
  6994  ad75 c981               	CMP	#$81			; compare with 1
  6995  ad77 9007               	BCC	LAB_2CAF		; branch if FAC1<1
  6996                          
  6997  ad79 a90c               	LDA	#<LAB_259C		; set 1 pointer low byte
  6998  ad7b a0b2               	LDY	#>LAB_259C		; set 1 pointer high byte
  6999  ad7d 2018a8             	JSR	LAB_26CA		; convert AY and do (AY)/FAC1
  7000                          LAB_2CAF
  7001  ad80 a9eb               	LDA	#<LAB_2CC9		; set pointer low byte to counter
  7002  ad82 a0b1               	LDY	#>LAB_2CC9		; set pointer high byte to counter
  7003  ad84 2068ac             	JSR	LAB_2B6E		; ^2 then series evaluation
  7004  ad87 68                 	PLA				; restore old FAC1 exponent
  7005  ad88 c981               	CMP	#$81			; compare with 1
  7006  ad8a 9007               	BCC	LAB_2CC2		; branch if FAC1<1
  7007                          
  7008  ad8c a9d2               	LDA	#<LAB_2C78		; set (pi/2) pointer low byte
  7009  ad8e a0b1               	LDY	#>LAB_2C78		; set (pi/2) pointer high byte
  7010  ad90 20baa5             	JSR	LAB_2455		; perform subtraction, (AY) from FAC1
  7011                          LAB_2CC2
  7012  ad93 68                 	PLA				; restore FAC1 sign
  7013  ad94 1016               	BPL	LAB_2D04		; exit if was +ve
  7014                          
  7015  ad96 4c0bac             	JMP	LAB_GTHAN		; else do - FAC1 and return
  7016                          
  7017                          ; perform BITSET
  7018                          
  7019                          LAB_BITSET
  7020  ad99 20efa4             	JSR	LAB_GADB		; get two parameters for POKE or WAIT
  7021  ad9c e008               	CPX	#$08			; only 0 to 7 are allowed
  7022  ad9e b020               	BCS	FCError		; branch if > 7
  7023                          
  7024  ada0 a900               	LDA	#$00			; clear A
  7025  ada2 38                 	SEC				; set the carry
  7026                          S_Bits
  7027  ada3 2a                 	ROL				; shift bit
  7028  ada4 ca                 	DEX				; decrement bit number
  7029  ada5 10fc               	BPL	S_Bits		; loop if still +ve
  7030                          
  7031  ada7 e8                 	INX				; make X = $00
  7032  ada8 0111               	ORA	(Itempl,X)		; or with byte via temporary integer (addr)
  7033  adaa 8111               	STA	(Itempl,X)		; save byte via temporary integer (addr)
  7034                          LAB_2D04
  7035  adac 60                 	RTS
  7036                          
  7037                          ; perform BITCLR
  7038                          
  7039                          LAB_BITCLR
  7040  adad 20efa4             	JSR	LAB_GADB		; get two parameters for POKE or WAIT
  7041  adb0 e008               	CPX	#$08			; only 0 to 7 are allowed
  7042  adb2 b00c               	BCS	FCError		; branch if > 7
  7043                          
  7044  adb4 a9ff               	LDA	#$FF			; set A
  7045                          S_Bitc
  7046  adb6 2a                 	ROL				; shift bit
  7047  adb7 ca                 	DEX				; decrement bit number
  7048  adb8 10fc               	BPL	S_Bitc		; loop if still +ve
  7049                          
  7050  adba e8                 	INX				; make X = $00
  7051  adbb 2111               	AND	(Itempl,X)		; and with byte via temporary integer (addr)
  7052  adbd 8111               	STA	(Itempl,X)		; save byte via temporary integer (addr)
  7053  adbf 60                 	RTS
  7054                          
  7055                          FCError
  7056  adc0 4c409f             	JMP	LAB_FCER		; do function call error then warm start
  7057                          
  7058                          ; perform BITTST()
  7059                          
  7060                          LAB_BTST
  7061  adc3 20bc00             	JSR	LAB_IGBY		; increment BASIC pointer
  7062  adc6 20efa4             	JSR	LAB_GADB		; get two parameters for POKE or WAIT
  7063  adc9 e008               	CPX	#$08			; only 0 to 7 are allowed
  7064  adcb b0f3               	BCS	FCError		; branch if > 7
  7065                          
  7066  adcd 20c200             	JSR	LAB_GBYT		; get next BASIC byte
  7067  add0 c929               	CMP	#')'			; is next character ")"
  7068  add2 f003               	BEQ	TST_OK		; if ")" go do rest of function
  7069                          
  7070  add4 4c199c             	JMP	LAB_SNER		; do syntax error then warm start
  7071                          
  7072                          TST_OK
  7073  add7 20bc00             	JSR	LAB_IGBY		; update BASIC execute pointer (to character past ")")
  7074  adda a900               	LDA	#$00			; clear A
  7075  addc 38                 	SEC				; set the carry
  7076                          T_Bits
  7077  addd 2a                 	ROL				; shift bit
  7078  adde ca                 	DEX				; decrement bit number
  7079  addf 10fc               	BPL	T_Bits		; loop if still +ve
  7080                          
  7081  ade1 e8                 	INX				; make X = $00
  7082  ade2 2111               	AND	(Itempl,X)		; AND with byte via temporary integer (addr)
  7083  ade4 f002               	BEQ	LAB_NOTT		; branch if zero (already correct)
  7084                          
  7085  ade6 a9ff               	LDA	#$FF			; set for -1 result
  7086                          LAB_NOTT
  7087  ade8 4c11a9             	JMP	LAB_27DB		; go do SGN tail
  7088                          
  7089                          ; perform BIN$()
  7090                          
  7091                          LAB_BINS
  7092  adeb e019               	CPX	#$19			; max + 1
  7093  aded b048               	BCS	BinFErr		; exit if too big ( > or = )
  7094                          
  7095  adef 8678               	STX	TempB			; save # of characters ($00 = leading zero remove)
  7096  adf1 a918               	LDA	#$18			; need A byte long space
  7097  adf3 2051a1             	JSR	LAB_MSSP		; make string space A bytes long
  7098  adf6 a017               	LDY	#$17			; set index
  7099  adf8 a218               	LDX	#$18			; character count
  7100                          NextB1
  7101  adfa 4611               	LSR	nums_1		; shift highest byte
  7102  adfc 6612               	ROR	nums_2		; shift middle byte
  7103  adfe 6613               	ROR	nums_3		; shift lowest byte bit 0 to carry
  7104  ae00 8a                 	TXA				; load with "0"/2
  7105  ae01 2a                 	ROL				; shift in carry
  7106  ae02 91ad               	STA	(str_pl),Y		; save to temp string + index
  7107  ae04 88                 	DEY				; decrement index
  7108  ae05 10f3               	BPL	NextB1		; loop if not done
  7109                          
  7110  ae07 a578               	LDA	TempB			; get # of characters
  7111  ae09 f00a               	BEQ	EndBHS		; branch if truncate
  7112                          
  7113  ae0b aa                 	TAX				; copy length to X
  7114  ae0c 38                 	SEC				; set carry for add !
  7115  ae0d 49ff               	EOR	#$FF			; 1's complement
  7116  ae0f 6918               	ADC	#$18			; add 24d
  7117  ae11 f01c               	BEQ	GoPr2			; if zero print whole string
  7118                          
  7119  ae13 d00f               	BNE	GoPr1			; else go make output string
  7120                          	
  7121                          ; this is the exit code and is also used by HEX$()
  7122                          ; truncate string to remove leading "0"s
  7123                          
  7124                          EndBHS
  7125  ae15 a8                 	TAY				; clear index (A=0, X=length here)
  7126                          NextB2
  7127  ae16 b1ad               	LDA	(str_pl),Y		; get character from string
  7128  ae18 c930               	CMP	#'0'			; compare with "0"
  7129  ae1a d007               	BNE	GoPr			; if not "0" then go print string from here
  7130                          
  7131  ae1c ca                 	DEX				; decrement character count
  7132  ae1d f003               	BEQ	GoPr3			; if zero then end of string so go print it
  7133                          
  7134  ae1f c8                 	INY				; else increment index
  7135  ae20 10f4               	BPL	NextB2		; loop always
  7136                          
  7137                          ; make fixed length output string - ignore overflows!
  7138                          
  7139                          GoPr3
  7140  ae22 e8                 	INX				; need at least 1 character
  7141                          GoPr
  7142  ae23 98                 	TYA				; copy result
  7143                          GoPr1
  7144  ae24 18                 	CLC				; clear carry for add
  7145  ae25 65ad               	ADC	str_pl		; add low address
  7146  ae27 85ad               	STA	str_pl		; save low address
  7147  ae29 a900               	LDA	#$00			; do high byte
  7148  ae2b 65ae               	ADC	str_ph		; add high address
  7149  ae2d 85ae               	STA	str_ph		; save high address
  7150                          GoPr2
  7151  ae2f 86ac               	STX	str_ln		; X holds string length
  7152  ae31 20bc00             	JSR	LAB_IGBY		; update BASIC execute pointer (to character past ")")
  7153  ae34 4c9ca1             	JMP	LAB_RTST		; check for space on descriptor stack then put address
  7154                          					; and length on descriptor stack and update stack pointers
  7155                          
  7156                          BinFErr
  7157  ae37 4c409f             	JMP	LAB_FCER		; do function call error then warm start
  7158                          
  7159                          ; perform HEX$()
  7160                          
  7161                          LAB_HEXS
  7162  ae3a e007               	CPX	#$07			; max + 1
  7163  ae3c b0f9               	BCS	BinFErr		; exit if too big ( > or = )
  7164                          
  7165  ae3e 8678               	STX	TempB			; save # of characters
  7166                          
  7167  ae40 a906               	LDA	#$06			; need 6 bytes for string
  7168  ae42 2051a1             	JSR	LAB_MSSP		; make string space A bytes long
  7169  ae45 a005               	LDY	#$05			; set string index
  7170                          
  7171  ae47 f8                 	SED				; need decimal mode for nibble convert
  7172  ae48 a513               	LDA	nums_3		; get lowest byte
  7173  ae4a 2068ae             	JSR	LAB_A2HX		; convert A to ASCII hex byte and output
  7174  ae4d a512               	LDA	nums_2		; get middle byte
  7175  ae4f 2068ae             	JSR	LAB_A2HX		; convert A to ASCII hex byte and output
  7176  ae52 a511               	LDA	nums_1		; get highest byte
  7177  ae54 2068ae             	JSR	LAB_A2HX		; convert A to ASCII hex byte and output
  7178  ae57 d8                 	CLD				; back to binary
  7179                          
  7180  ae58 a206               	LDX	#$06			; character count
  7181  ae5a a578               	LDA	TempB			; get # of characters
  7182  ae5c f0b7               	BEQ	EndBHS		; branch if truncate
  7183                          
  7184  ae5e aa                 	TAX				; copy length to X
  7185  ae5f 38                 	SEC				; set carry for add !
  7186  ae60 49ff               	EOR	#$FF			; 1's complement
  7187  ae62 6906               	ADC	#$06			; add 6d
  7188  ae64 f0c9               	BEQ	GoPr2			; if zero print whole string
  7189                          
  7190  ae66 d0bc               	BNE	GoPr1			; else go make output string (branch always)
  7191                          
  7192                          ; convert A to ASCII hex byte and output .. note set decimal mode before calling
  7193                          
  7194                          LAB_A2HX
  7195  ae68 aa                 	TAX				; save byte
  7196  ae69 290f               	AND	#$0F			; mask off top bits
  7197  ae6b 2073ae             	JSR	LAB_AL2X		; convert low nibble to ASCII and output
  7198  ae6e 8a                 	TXA				; get byte back
  7199  ae6f 4a                 	LSR				; /2	shift high nibble to low nibble
  7200  ae70 4a                 	LSR				; /4
  7201  ae71 4a                 	LSR				; /8
  7202  ae72 4a                 	LSR				; /16
  7203                          LAB_AL2X
  7204  ae73 c90a               	CMP	#$0A			; set carry for +1 if >9
  7205  ae75 6930               	ADC	#'0'			; add ASCII "0"
  7206  ae77 91ad               	STA	(str_pl),Y		; save to temp string
  7207  ae79 88                 	DEY				; decrement counter
  7208  ae7a 60                 	RTS
  7209                          
  7210                          LAB_NLTO
  7211  ae7b 85ac               	STA	FAC1_e		; save FAC1 exponent
  7212  ae7d a900               	LDA	#$00			; clear sign compare
  7213                          LAB_MLTE
  7214  ae7f 85b8               	STA	FAC_sc		; save sign compare (FAC1 EOR FAC2)
  7215  ae81 8a                 	TXA				; restore character
  7216  ae82 205caa             	JSR	LAB_2912		; evaluate new ASCII digit
  7217                          
  7218                          ; gets here if the first character was "$" for hex
  7219                          ; get hex number
  7220                          
  7221                          LAB_CHEX
  7222  ae85 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  7223  ae88 900a               	BCC	LAB_ISHN		; branch if numeric character
  7224                          
  7225  ae8a 0920               	ORA	#$20			; case convert, allow "A" to "F" and "a" to "f"
  7226  ae8c e961               	SBC	#'a'			; subtract "a" (carry set here)
  7227  ae8e c906               	CMP	#$06			; compare normalised with $06 (max+1)
  7228  ae90 b02a               	BCS	LAB_EXCH		; exit if >"f" or <"0"
  7229                          
  7230  ae92 690a               	ADC	#$0A			; convert to nibble
  7231                          LAB_ISHN
  7232  ae94 290f               	AND	#$0F			; convert to binary
  7233  ae96 aa                 	TAX				; save nibble
  7234  ae97 a5ac               	LDA	FAC1_e		; get FAC1 exponent
  7235  ae99 f0e4               	BEQ	LAB_MLTE		; skip multiply if zero
  7236                          
  7237  ae9b 6904               	ADC	#$04			; add four to exponent (*16 - carry clear here)
  7238  ae9d 90dc               	BCC	LAB_NLTO		; if no overflow do evaluate digit
  7239                          
  7240                          LAB_MLTO
  7241  ae9f 4cdaa6             	JMP	LAB_2564		; do overflow error and warm start
  7242                          
  7243                          LAB_NXCH
  7244  aea2 aa                 	TAX				; save bit
  7245  aea3 a5ac               	LDA	FAC1_e		; get FAC1 exponent
  7246  aea5 f006               	BEQ	LAB_MLBT		; skip multiply if zero
  7247                          
  7248  aea7 e6ac               	INC	FAC1_e		; increment FAC1 exponent (*2)
  7249  aea9 f0f4               	BEQ	LAB_MLTO		; do overflow error if = $00
  7250                          
  7251  aeab a900               	LDA	#$00			; clear sign compare
  7252                          LAB_MLBT
  7253  aead 85b8               	STA	FAC_sc		; save sign compare (FAC1 EOR FAC2)
  7254  aeaf 8a                 	TXA				; restore bit
  7255  aeb0 205caa             	JSR	LAB_2912		; evaluate new ASCII digit
  7256                          
  7257                          ; gets here if the first character was  "%" for binary
  7258                          ; get binary number
  7259                          
  7260                          LAB_CBIN
  7261  aeb3 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  7262  aeb6 4930               	EOR	#'0'			; convert "0" to 0 etc.
  7263  aeb8 c902               	CMP	#$02			; compare with max+1
  7264  aeba 90e6               	BCC	LAB_NXCH		; branch exit if < 2
  7265                          
  7266                          LAB_EXCH
  7267  aebc 4c41aa             	JMP	LAB_28F6		; evaluate -ve flag and return
  7268                          
  7269                          ; ctrl-c check routine. includes limited "life" byte save for INGET routine
  7270                          ; now also the code that checks to see if an interrupt has occurred
  7271                          
  7272                          CTRLC
  7273  aebf ad0003             	LDA	ccflag		; get [CTRL-C] check flag
  7274  aec2 d018               	BNE	LAB_FBA2		; exit if inhibited
  7275                          
  7276  aec4 2016b1             	JSR	V_INPT		; scan input device
  7277  aec7 900b               	BCC	LAB_FBA0		; exit if buffer empty
  7278                          
  7279  aec9 8d0103             	STA	ccbyte		; save received byte
  7280  aecc a220               	LDX	#$20			; "life" timer for bytes
  7281  aece 8e0203             	STX	ccnull		; set countdown
  7282  aed1 4c2e95             	JMP	LAB_1636		; return to BASIC
  7283                          
  7284                          LAB_FBA0
  7285  aed4 ae0203             	LDX	ccnull		; get countdown byte
  7286  aed7 f003               	BEQ	LAB_FBA2		; exit if finished
  7287                          
  7288  aed9 ce0203             	DEC	ccnull		; else decrement countdown
  7289                          LAB_FBA2
  7290  aedc a2dc               	LDX	#NmiBase		; set pointer to NMI values
  7291  aede 20e7ae             	JSR	LAB_CKIN		; go check interrupt
  7292  aee1 a2df               	LDX	#IrqBase		; set pointer to IRQ values
  7293  aee3 20e7ae             	JSR	LAB_CKIN		; go check interrupt
  7294                          LAB_CRTS
  7295  aee6 60                 	RTS
  7296                          
  7297                          ; check whichever interrupt is indexed by X
  7298                          
  7299                          LAB_CKIN
  7300  aee7 b500               	LDA	PLUS_0,X		; get interrupt flag byte
  7301  aee9 10fb               	BPL	LAB_CRTS		; branch if interrupt not enabled
  7302                          
  7303                          ; we disable the interrupt here and make two new commands RETIRQ and RETNMI to
  7304                          ; automatically enable the interrupt when we exit
  7305                          
  7306  aeeb 0a                 	ASL				; move happened bit to setup bit
  7307  aeec 2940               	AND	#$40			; mask happened bits
  7308  aeee f0f6               	BEQ	LAB_CRTS		; if no interrupt then exit
  7309                          
  7310  aef0 9500               	STA	PLUS_0,X		; save interrupt flag byte
  7311                          
  7312  aef2 8a                 	TXA				; copy index ..
  7313  aef3 a8                 	TAY				; .. to Y
  7314                          
  7315  aef4 68                 	PLA				; dump return address low byte, call from CTRL-C
  7316  aef5 68                 	PLA				; dump return address high byte
  7317                          
  7318  aef6 a905               	LDA	#$05			; need 5 bytes for GOSUB
  7319  aef8 200e91             	JSR	LAB_1212		; check room on stack for A bytes
  7320  aefb a5c4               	LDA	Bpntrh		; get BASIC execute pointer high byte
  7321  aefd 48                 	PHA				; push on stack
  7322  aefe a5c3               	LDA	Bpntrl		; get BASIC execute pointer low byte
  7323  af00 48                 	PHA				; push on stack
  7324  af01 a588               	LDA	Clineh		; get current line high byte
  7325  af03 48                 	PHA				; push on stack
  7326  af04 a587               	LDA	Clinel		; get current line low byte
  7327  af06 48                 	PHA				; push on stack
  7328  af07 a98d               	LDA	#TK_GOSUB		; token for GOSUB
  7329  af09 48                 	PHA				; push on stack
  7330                          
  7331  af0a b90100             	LDA	PLUS_1,Y		; get interrupt code pointer low byte
  7332  af0d 85c3               	STA	Bpntrl		; save as BASIC execute pointer low byte
  7333  af0f b90200             	LDA	PLUS_2,Y		; get interrupt code pointer high byte
  7334  af12 85c4               	STA	Bpntrh		; save as BASIC execute pointer high byte
  7335                          
  7336  af14 4cd394             	JMP	LAB_15C2		; go do interpreter inner loop
  7337                          					; can't RTS, we used the stack! the RTS from the ctrl-c
  7338                          					; check will be taken when the RETIRQ/RETNMI/RETURN is
  7339                          					; executed at the end of the subroutine
  7340                          
  7341                          ; get byte from input device, no waiting
  7342                          ; returns with carry set if byte in A
  7343                          
  7344                          INGET
  7345  af17 2016b1             	JSR	V_INPT		; call scan input device
  7346  af1a b009               	BCS	LAB_FB95		; if byte go reset timer
  7347                          
  7348  af1c ad0203             	LDA	ccnull		; get countdown
  7349  af1f f009               	BEQ	LAB_FB96		; exit if empty
  7350                          
  7351  af21 ad0103             	LDA	ccbyte		; get last received byte
  7352  af24 38                 	SEC				; flag we got a byte
  7353                          LAB_FB95
  7354  af25 a200               	LDX	#$00			; clear X
  7355  af27 8e0203             	STX	ccnull		; clear timer because we got a byte
  7356                          LAB_FB96
  7357  af2a 60                 	RTS
  7358                          
  7359                          ; these routines only enable the interrupts if the set-up flag is set
  7360                          ; if not they have no effect
  7361                          
  7362                          ; perform IRQ {ON|OFF|CLEAR}
  7363                          
  7364                          LAB_IRQ
  7365  af2b a2df               	LDX	#IrqBase		; set pointer to IRQ values
  7366  af2d 2c                 	!text	$2C			; make next line BIT abs.
  7367                          
  7368                          ; perform NMI {ON|OFF|CLEAR}
  7369                          
  7370                          LAB_NMI
  7371  af2e a2dc               	LDX	#NmiBase		; set pointer to NMI values
  7372  af30 c993               	CMP	#TK_ON		; compare with token for ON
  7373  af32 f011               	BEQ	LAB_INON		; go turn on interrupt
  7374                          
  7375  af34 c9b7               	CMP	#TK_OFF		; compare with token for OFF
  7376  af36 f007               	BEQ	LAB_IOFF		; go turn off interrupt
  7377                          
  7378  af38 49a4               	EOR	#TK_CLEAR		; compare with token for CLEAR, A = $00 if = TK_CLEAR
  7379  af3a f00e               	BEQ	LAB_INEX		; go clear interrupt flags and return
  7380                          
  7381  af3c 4c199c             	JMP	LAB_SNER		; do syntax error then warm start
  7382                          
  7383                          LAB_IOFF
  7384  af3f a97f               	LDA	#$7F			; clear A
  7385  af41 3500               	AND	PLUS_0,X		; AND with interrupt setup flag
  7386  af43 1005               	BPL	LAB_INEX		; go clear interrupt enabled flag and return
  7387                          
  7388                          LAB_INON
  7389  af45 b500               	LDA	PLUS_0,X		; get interrupt setup flag
  7390  af47 0a                 	ASL				; Shift bit to enabled flag
  7391  af48 1500               	ORA	PLUS_0,X		; OR with flag byte
  7392                          LAB_INEX
  7393  af4a 9500               	STA	PLUS_0,X		; save interrupt flag byte
  7394  af4c 4cbc00             	JMP	LAB_IGBY		; update BASIC execute pointer and return
  7395                          
  7396                          ; these routines set up the pointers and flags for the interrupt routines
  7397                          ; note that the interrupts are also enabled by these commands
  7398                          
  7399                          ; perform ON IRQ
  7400                          
  7401                          LAB_SIRQ
  7402  af4f 58                 	CLI				; enable interrupts
  7403  af50 a2df               	LDX	#IrqBase		; set pointer to IRQ values
  7404  af52 2c                 	!text	$2C			; make next line BIT abs.
  7405                          
  7406                          ; perform ON NMI
  7407                          
  7408                          LAB_SNMI
  7409  af53 a2dc               	LDX	#NmiBase		; set pointer to NMI values
  7410                          
  7411  af55 8678               	STX	TempB			; save interrupt pointer
  7412  af57 20bc00             	JSR	LAB_IGBY		; increment and scan memory (past token)
  7413  af5a 207197             	JSR	LAB_GFPN		; get fixed-point number into temp integer
  7414  af5d a579               	LDA	Smeml			; get start of mem low byte
  7415  af5f a67a               	LDX	Smemh			; get start of mem high byte
  7416  af61 203f93             	JSR	LAB_SHLN		; search Basic for temp integer line number from AX
  7417  af64 b003               	BCS	LAB_LFND		; if carry set go set-up interrupt
  7418                          
  7419  af66 4c8e96             	JMP	LAB_16F7		; else go do "Undefined statement" error and warm start
  7420                          
  7421                          LAB_LFND
  7422  af69 a678               	LDX	TempB			; get interrupt pointer
  7423  af6b a5aa               	LDA	Baslnl		; get pointer low byte
  7424  af6d e901               	SBC	#$01			; -1 (carry already set for subtract)
  7425  af6f 9501               	STA	PLUS_1,X		; save as interrupt pointer low byte
  7426  af71 a5ab               	LDA	Baslnh		; get pointer high byte
  7427  af73 e900               	SBC	#$00			; subtract carry
  7428  af75 9502               	STA	PLUS_2,X		; save as interrupt pointer high byte
  7429                          
  7430  af77 a9c0               	LDA	#$C0			; set interrupt enabled/setup bits
  7431  af79 9500               	STA	PLUS_0,X		; set interrupt flags
  7432                          LAB_IRTS
  7433  af7b 60                 	RTS
  7434                          
  7435                          ; return from IRQ service, restores the enabled flag.
  7436                          
  7437                          ; perform RETIRQ
  7438                          
  7439                          LAB_RETIRQ
  7440  af7c d0fd               	BNE	LAB_IRTS		; exit if following token (to allow syntax error)
  7441                          
  7442  af7e a5df               	LDA	IrqBase		; get interrupt flags
  7443  af80 0a                 	ASL				; copy setup to enabled (b7)
  7444  af81 05df               	ORA	IrqBase		; OR in setup flag
  7445  af83 85df               	STA	IrqBase		; save enabled flag
  7446  af85 4c9596             	JMP	LAB_16E8		; go do rest of RETURN
  7447                          
  7448                          ; return from NMI service, restores the enabled flag.
  7449                          
  7450                          ; perform RETNMI
  7451                          
  7452                          LAB_RETNMI
  7453  af88 d0f1               	BNE	LAB_IRTS		; exit if following token (to allow syntax error)
  7454                          
  7455  af8a a5dc               	LDA	NmiBase		; get set-up flag
  7456  af8c 0a                 	ASL				; copy setup to enabled (b7)
  7457  af8d 05dc               	ORA	NmiBase		; OR in setup flag
  7458  af8f 85dc               	STA	NmiBase		; save enabled flag
  7459  af91 4c9596             	JMP	LAB_16E8		; go do rest of RETURN
  7460                          
  7461                          ; MAX() MIN() pre process
  7462                          
  7463                          LAB_MMPP
  7464  af94 20009b             	JSR	LAB_EVEZ		; process expression
  7465  af97 4ce79a             	JMP	LAB_CTNM		; check if source is numeric, else do type mismatch
  7466                          
  7467                          ; perform MAX()
  7468                          
  7469                          LAB_MAX
  7470  af9a 20c8af             	JSR	LAB_PHFA		; push FAC1, evaluate expression,
  7471                          					; pull FAC2 and compare with FAC1
  7472  af9d 10fb               	BPL	LAB_MAX		; branch if no swap to do
  7473                          
  7474  af9f a5b4               	LDA	FAC2_1		; get FAC2 mantissa1
  7475  afa1 0980               	ORA	#$80			; set top bit (clear sign from compare)
  7476  afa3 85b4               	STA	FAC2_1		; save FAC2 mantissa1
  7477  afa5 20daa5             	JSR	LAB_279B		; copy FAC2 to FAC1
  7478  afa8 f0f0               	BEQ	LAB_MAX		; go do next (branch always)
  7479                          
  7480                          ; perform MIN()
  7481                          
  7482                          LAB_MIN
  7483  afaa 20c8af             	JSR	LAB_PHFA		; push FAC1, evaluate expression,
  7484                          					; pull FAC2 and compare with FAC1
  7485  afad 30fb               	BMI	LAB_MIN		; branch if no swap to do
  7486                          
  7487  afaf f0f9               	BEQ	LAB_MIN		; branch if no swap to do
  7488                          
  7489  afb1 a5b4               	LDA	FAC2_1		; get FAC2 mantissa1
  7490  afb3 0980               	ORA	#$80			; set top bit (clear sign from compare)
  7491  afb5 85b4               	STA	FAC2_1		; save FAC2 mantissa1
  7492  afb7 20daa5             	JSR	LAB_279B		; copy FAC2 to FAC1
  7493  afba f0ee               	BEQ	LAB_MIN		; go do next (branch always)
  7494                          
  7495                          ; exit routine. don't bother returning to the loop code
  7496                          ; check for correct exit, else so syntax error
  7497                          
  7498                          LAB_MMEC
  7499  afbc c929               	CMP	#')'			; is it end of function?
  7500  afbe d005               	BNE	LAB_MMSE		; if not do MAX MIN syntax error
  7501                          
  7502  afc0 68                 	PLA				; dump return address low byte
  7503  afc1 68                 	PLA				; dump return address high byte
  7504  afc2 4cbc00             	JMP	LAB_IGBY		; update BASIC execute pointer (to chr past ")")
  7505                          
  7506                          LAB_MMSE
  7507  afc5 4c199c             	JMP	LAB_SNER		; do syntax error then warm start
  7508                          
  7509                          ; check for next, evaluate and return or exit
  7510                          ; this is the routine that does most of the work
  7511                          
  7512                          LAB_PHFA
  7513  afc8 20c200             	JSR	LAB_GBYT		; get next BASIC byte
  7514  afcb c92c               	CMP	#','			; is there more ?
  7515  afcd d0ed               	BNE	LAB_MMEC		; if not go do end check
  7516                          
  7517                          					; push FAC1
  7518  afcf 20f0a8             	JSR	LAB_27BA		; round FAC1
  7519  afd2 a5b0               	LDA	FAC1_s		; get FAC1 sign
  7520  afd4 097f               	ORA	#$7F			; set all non sign bits
  7521  afd6 25ad               	AND	FAC1_1		; AND FAC1 mantissa1 (AND in sign bit)
  7522  afd8 48                 	PHA				; push on stack
  7523  afd9 a5ae               	LDA	FAC1_2		; get FAC1 mantissa2
  7524  afdb 48                 	PHA				; push on stack
  7525  afdc a5af               	LDA	FAC1_3		; get FAC1 mantissa3
  7526  afde 48                 	PHA				; push on stack
  7527  afdf a5ac               	LDA	FAC1_e		; get FAC1 exponent
  7528  afe1 48                 	PHA				; push on stack
  7529                          
  7530  afe2 20bc00             	JSR	LAB_IGBY		; scan and get next BASIC byte (after ",")
  7531  afe5 20e49a             	JSR	LAB_EVNM		; evaluate expression and check is numeric,
  7532                          					; else do type mismatch
  7533                          
  7534                          					; pop FAC2 (MAX/MIN expression so far)
  7535  afe8 68                 	PLA				; pop exponent
  7536  afe9 85b3               	STA	FAC2_e		; save FAC2 exponent
  7537  afeb 68                 	PLA				; pop mantissa3
  7538  afec 85b6               	STA	FAC2_3		; save FAC2 mantissa3
  7539  afee 68                 	PLA				; pop mantissa1
  7540  afef 85b5               	STA	FAC2_2		; save FAC2 mantissa2
  7541  aff1 68                 	PLA				; pop sign/mantissa1
  7542  aff2 85b4               	STA	FAC2_1		; save FAC2 sign/mantissa1
  7543  aff4 85b7               	STA	FAC2_s		; save FAC2 sign
  7544                          
  7545                          					; compare FAC1 with (packed) FAC2
  7546  aff6 a9b3               	LDA	#<FAC2_e		; set pointer low byte to FAC2
  7547  aff8 a000               	LDY	#>FAC2_e		; set pointer high byte to FAC2
  7548  affa 4c2ea9             	JMP	LAB_27F8		; compare FAC1 with FAC2 (AY) and return
  7549                          					; returns A=$00 if FAC1 = (AY)
  7550                          					; returns A=$01 if FAC1 > (AY)
  7551                          					; returns A=$FF if FAC1 < (AY)
  7552                          
  7553                          ; perform WIDTH
  7554                          
  7555                          LAB_WDTH
  7556  affd c92c               	CMP	#','			; is next byte ","
  7557  afff f01b               	BEQ	LAB_TBSZ		; if so do tab size
  7558                          
  7559  b001 20a3a4             	JSR	LAB_GTBY		; get byte parameter
  7560  b004 8a                 	TXA				; copy width to A
  7561  b005 f00a               	BEQ	LAB_NSTT		; branch if set for infinite line
  7562                          
  7563  b007 e010               	CPX	#$10			; else make min width = 16d
  7564  b009 9045               	BCC	TabErr		; if less do function call error and exit
  7565                          
  7566                          ; this next compare ensures that we can't exit WIDTH via an error leaving the
  7567                          ; tab size greater than the line length.
  7568                          
  7569  b00b e464               	CPX	TabSiz		; compare with tab size
  7570  b00d b002               	BCS	LAB_NSTT		; branch if >= tab size
  7571                          
  7572  b00f 8664               	STX	TabSiz		; else make tab size = terminal width
  7573                          LAB_NSTT
  7574  b011 860f               	STX	TWidth		; set the terminal width
  7575  b013 20c200             	JSR	LAB_GBYT		; get BASIC byte back
  7576  b016 f01a               	BEQ	WExit			; exit if no following
  7577                          
  7578  b018 c92c               	CMP	#','			; else is it ","
  7579  b01a d0a9               	BNE	LAB_MMSE		; if not do syntax error
  7580                          
  7581                          LAB_TBSZ
  7582  b01c 20a0a4             	JSR	LAB_SGBY		; scan and get byte parameter
  7583  b01f 8a                 	TXA				; copy TAB size
  7584  b020 302e               	BMI	TabErr		; if >127 do function call error and exit
  7585                          
  7586  b022 e001               	CPX	#$01			; compare with min-1
  7587  b024 902a               	BCC	TabErr		; if <=1 do function call error and exit
  7588                          
  7589  b026 a50f               	LDA	TWidth		; set flags for width
  7590  b028 f006               	BEQ	LAB_SVTB		; skip check if infinite line
  7591                          
  7592  b02a e40f               	CPX	TWidth		; compare TAB with width
  7593  b02c f002               	BEQ	LAB_SVTB		; ok if =
  7594                          
  7595  b02e b020               	BCS	TabErr		; branch if too big
  7596                          
  7597                          LAB_SVTB
  7598  b030 8664               	STX	TabSiz		; save TAB size
  7599                          
  7600                          ; calculate tab column limit from TAB size. The Iclim is set to the last tab
  7601                          ; position on a line that still has at least one whole tab width between it
  7602                          ; and the end of the line.
  7603                          
  7604                          WExit
  7605  b032 a50f               	LDA	TWidth		; get width
  7606  b034 f006               	BEQ	LAB_SULP		; branch if infinite line
  7607                          
  7608  b036 c564               	CMP	TabSiz		; compare with tab size
  7609  b038 b003               	BCS	LAB_WDLP		; branch if >= tab size
  7610                          
  7611  b03a 8564               	STA	TabSiz		; else make tab size = terminal width
  7612                          LAB_SULP
  7613  b03c 38                 	SEC				; set carry for subtract
  7614                          LAB_WDLP
  7615  b03d e564               	SBC	TabSiz		; subtract tab size
  7616  b03f b0fc               	BCS	LAB_WDLP		; loop while no borrow
  7617                          
  7618  b041 6564               	ADC	TabSiz		; add tab size back
  7619  b043 18                 	CLC				; clear carry for add
  7620  b044 6564               	ADC	TabSiz		; add tab size back again
  7621  b046 8510               	STA	Iclim			; save for now
  7622  b048 a50f               	LDA	TWidth		; get width back
  7623  b04a 38                 	SEC				; set carry for subtract
  7624  b04b e510               	SBC	Iclim			; subtract remainder
  7625  b04d 8510               	STA	Iclim			; save tab column limit
  7626                          LAB_NOSQ
  7627  b04f 60                 	RTS
  7628                          
  7629                          TabErr
  7630  b050 4c409f             	JMP	LAB_FCER		; do function call error then warm start
  7631                          
  7632                          ; perform SQR()
  7633                          
  7634                          LAB_SQR
  7635  b053 a5b0               	LDA	FAC1_s		; get FAC1 sign
  7636  b055 30f9               	BMI	TabErr		; if -ve do function call error
  7637                          
  7638  b057 a5ac               	LDA	FAC1_e		; get exponent
  7639  b059 f0f4               	BEQ	LAB_NOSQ		; if zero just return
  7640                          
  7641                          					; else do root
  7642  b05b 20e1a8             	JSR	LAB_27AB		; round and copy FAC1 to FAC2
  7643  b05e a900               	LDA	#$00			; clear A
  7644                          
  7645  b060 8577               	STA	FACt_3		; clear remainder
  7646  b062 8576               	STA	FACt_2		; ..
  7647  b064 8575               	STA	FACt_1		; ..
  7648  b066 8578               	STA	TempB			; ..
  7649                          
  7650  b068 85af               	STA	FAC1_3		; clear root
  7651  b06a 85ae               	STA	FAC1_2		; ..
  7652  b06c 85ad               	STA	FAC1_1		; ..
  7653                          
  7654  b06e a218               	LDX	#$18			; 24 pairs of bits to do
  7655  b070 a5b3               	LDA	FAC2_e		; get exponent
  7656  b072 4a                 	LSR				; check odd/even
  7657  b073 b00e               	BCS	LAB_SQE2		; if odd only 1 shift first time
  7658                          
  7659                          LAB_SQE1
  7660  b075 06b6               	ASL	FAC2_3		; shift highest bit of number ..
  7661  b077 26b5               	ROL	FAC2_2		; ..
  7662  b079 26b4               	ROL	FAC2_1		; ..
  7663  b07b 2677               	ROL	FACt_3		; .. into remainder
  7664  b07d 2676               	ROL	FACt_2		; ..
  7665  b07f 2675               	ROL	FACt_1		; ..
  7666  b081 2678               	ROL	TempB			; .. never overflows
  7667                          LAB_SQE2
  7668  b083 06b6               	ASL	FAC2_3		; shift highest bit of number ..
  7669  b085 26b5               	ROL	FAC2_2		; ..
  7670  b087 26b4               	ROL	FAC2_1		; ..
  7671  b089 2677               	ROL	FACt_3		; .. into remainder
  7672  b08b 2676               	ROL	FACt_2		; ..
  7673  b08d 2675               	ROL	FACt_1		; ..
  7674  b08f 2678               	ROL	TempB			; .. never overflows
  7675                          
  7676  b091 06af               	ASL	FAC1_3		; root = root * 2
  7677  b093 26ae               	ROL	FAC1_2		; ..
  7678  b095 26ad               	ROL	FAC1_1		; .. never overflows
  7679                          
  7680  b097 a5af               	LDA	FAC1_3		; get root low byte
  7681  b099 2a                 	ROL				; *2
  7682  b09a 855b               	STA	Temp3			; save partial low byte
  7683  b09c a5ae               	LDA	FAC1_2		; get root low mid byte
  7684  b09e 2a                 	ROL				; *2
  7685  b09f 855c               	STA	Temp3+1		; save partial low mid byte
  7686  b0a1 a5ad               	LDA	FAC1_1		; get root high mid byte
  7687  b0a3 2a                 	ROL				; *2
  7688  b0a4 855d               	STA	Temp3+2		; save partial high mid byte
  7689  b0a6 a900               	LDA	#$00			; get root high byte (always $00)
  7690  b0a8 2a                 	ROL				; *2
  7691  b0a9 855e               	STA	Temp3+3		; save partial high byte
  7692                          
  7693                          					; carry clear for subtract +1
  7694  b0ab a577               	LDA	FACt_3		; get remainder low byte
  7695  b0ad e55b               	SBC	Temp3			; subtract partial low byte
  7696  b0af 855b               	STA	Temp3			; save partial low byte
  7697                          
  7698  b0b1 a576               	LDA	FACt_2		; get remainder low mid byte
  7699  b0b3 e55c               	SBC	Temp3+1		; subtract partial low mid byte
  7700  b0b5 855c               	STA	Temp3+1		; save partial low mid byte
  7701                          
  7702  b0b7 a575               	LDA	FACt_1		; get remainder high mid byte
  7703  b0b9 e55d               	SBC	Temp3+2		; subtract partial high mid byte
  7704  b0bb a8                 	TAY				; copy partial high mid byte
  7705                          
  7706  b0bc a578               	LDA	TempB			; get remainder high byte
  7707  b0be e55e               	SBC	Temp3+3		; subtract partial high byte
  7708  b0c0 900e               	BCC	LAB_SQNS		; skip sub if remainder smaller
  7709                          
  7710  b0c2 8578               	STA	TempB			; save remainder high byte
  7711                          
  7712  b0c4 8475               	STY	FACt_1		; save remainder high mid byte
  7713                          
  7714  b0c6 a55c               	LDA	Temp3+1		; get remainder low mid byte
  7715  b0c8 8576               	STA	FACt_2		; save remainder low mid byte
  7716                          
  7717  b0ca a55b               	LDA	Temp3			; get partial low byte
  7718  b0cc 8577               	STA	FACt_3		; save remainder low byte
  7719                          
  7720  b0ce e6af               	INC	FAC1_3		; increment root low byte (never any rollover)
  7721                          LAB_SQNS
  7722  b0d0 ca                 	DEX				; decrement bit pair count
  7723  b0d1 d0a2               	BNE	LAB_SQE1		; loop if not all done
  7724                          
  7725  b0d3 38                 	SEC				; set carry for subtract
  7726  b0d4 a5b3               	LDA	FAC2_e		; get exponent
  7727  b0d6 e980               	SBC	#$80			; normalise
  7728  b0d8 6a                 	ROR				; /2 and re-bias to $80
  7729  b0d9 6900               	ADC	#$00			; add bit zero back in (allow for half shift)
  7730  b0db 85ac               	STA	FAC1_e		; save it
  7731  b0dd 4c4ba6             	JMP	LAB_24D5		; normalise FAC1 and return
  7732                          
  7733                          ; perform VARPTR()
  7734                          
  7735                          LAB_VARPTR
  7736  b0e0 20bc00             	JSR	LAB_IGBY		; increment and scan memory
  7737  b0e3 20c19d             	JSR	LAB_GVAR		; get var address
  7738  b0e6 20069c             	JSR	LAB_1BFB		; scan for ")" , else do syntax error then warm start
  7739  b0e9 a495               	LDY	Cvaral		; get var address low byte
  7740  b0eb a596               	LDA	Cvarah		; get var address high byte
  7741  b0ed 4c70a0             	JMP	LAB_AYFC		; save and convert integer AY to FAC1 and return
  7742                          
  7743                          ; perform PI
  7744                          
  7745                          LAB_PI
  7746  b0f0 a9e7               	LDA	#<LAB_2C7C		; set (2*pi) pointer low byte
  7747  b0f2 a0b1               	LDY	#>LAB_2C7C		; set (2*pi) pointer high byte
  7748  b0f4 2094a8             	JSR	LAB_UFAC		; unpack memory (AY) into FAC1
  7749  b0f7 c6ac               	DEC	FAC1_e		; make result = PI
  7750  b0f9 60                 	RTS
  7751                          
  7752                          ; perform TWOPI
  7753                          
  7754                          LAB_TWOPI
  7755  b0fa a9e7               	LDA	#<LAB_2C7C		; set (2*pi) pointer low byte
  7756  b0fc a0b1               	LDY	#>LAB_2C7C		; set (2*pi) pointer high byte
  7757  b0fe 4c94a8             	JMP	LAB_UFAC		; unpack memory (AY) into FAC1 and return
  7758                          
  7759                          LAB_DISPLAY
  7760  b101 20e49a             	JSR	LAB_EVNM		; evaluate expression and check is numeric,
  7761                          					; else do type mismatch
  7762  b104 2008a5             	JSR	LAB_F2FX		; save integer part of FAC1 in temporary integer
  7763  b107 a611               	ldx 	Itempl
  7764  b109 4c3ab9             	jmp 	basicMode2
  7765                          
  7766                          ; plot a pixel
  7767                          LAB_PLOT:
  7768  b10c 20efa4             	jsr LAB_GADB ; get two parameters
  7769  b10f 8a                 	txa
  7770  b110 a8                 	tay
  7771  b111 a611               	ldx Itempl
  7772                                  
  7773  b113 4c4bb9             	jmp doPlot
  7774                          
  7775                          ; system dependant i/o vectors
  7776                          ; these are in RAM and are set by the monitor at start-up
  7777                          
  7778                          V_INPT
  7779  b116 6c0503             	JMP	(VEC_IN)		; non halting scan input device
  7780                          V_OUTP
  7781  b119 6c0703             	JMP	(VEC_OUT)		; send byte to output device
  7782                          V_LOAD
  7783  b11c 6c0903             	JMP	(VEC_LD)		; load BASIC program
  7784                          V_SAVE
  7785  b11f 6c0b03             	JMP	(VEC_SV)		; save BASIC program
  7786                          
  7787                          ; The rest are tables messages and code for RAM
  7788                          
  7789                          ; the rest of the code is tables and BASIC start-up code
  7790                          
  7791                          PG2_TABS
  7792  b122 00                 	!text	$00			; ctrl-c flag		-	$00 = enabled
  7793  b123 00                 	!text	$00			; ctrl-c byte		-	GET needs this
  7794  b124 00                 	!text	$00			; ctrl-c byte timeout	-	GET needs this
  7795  b125 bfae               	!word	CTRLC			; ctrl c check vector
  7796                          ;	!word	xxxx			; non halting key input	-	monitor to set this
  7797                          ;	!word	xxxx			; output vector		-	monitor to set this
  7798                          ;	!word	xxxx			; load vector		-	monitor to set this
  7799                          ;	!word	xxxx			; save vector		-	monitor to set this
  7800                          PG2_TABE
  7801                          
  7802                          ; character get subroutine for zero page
  7803                          
  7804                          ; For a 1.8432MHz 6502 including the JSR and RTS
  7805                          ; fastest (>=":")	=  29 cycles =  15.7uS
  7806                          ; slowest (<":")	=  40 cycles =  21.7uS
  7807                          ; space skip	= +21 cycles = +11.4uS
  7808                          ; inc across page	=  +4 cycles =  +2.2uS
  7809                          
  7810                          ; the target address for the LDA at LAB_2CF4 becomes the BASIC execute pointer once the
  7811                          ; block is copied to it's destination, any non zero page address will do at assembly
  7812                          ; time, to assemble a three byte instruction.
  7813                          
  7814                          ; page 0 initialisation table from $BC
  7815                          ; increment and scan memory
  7816                          
  7817                          LAB_2CEE
  7818  b127 e6c3               	INC	Bpntrl		; increment BASIC execute pointer low byte
  7819  b129 d002               	BNE	LAB_2CF4		; branch if no carry
  7820                          					; else
  7821  b12b e6c4               	INC	Bpntrh		; increment BASIC execute pointer high byte
  7822                          
  7823                          ; page 0 initialisation table from $C2
  7824                          ; scan memory
  7825                          
  7826                          LAB_2CF4
  7827  b12d adffff             	LDA	$FFFF			; get byte to scan (addr set by call routine)
  7828  b130 c9ae               	CMP	#TK_ELSE		; compare with the token for ELSE
  7829  b132 f00e               	BEQ	LAB_2D05		; exit if ELSE, not numeric, carry set
  7830                          
  7831  b134 c93a               	CMP	#':'			; compare with ":"
  7832  b136 b00a               	BCS	LAB_2D05		; exit if >= ":", not numeric, carry set
  7833                          
  7834  b138 c920               	CMP	#' '			; compare with " "
  7835  b13a f0eb               	BEQ	LAB_2CEE		; if " " go do next
  7836                          
  7837  b13c 38                 	SEC				; set carry for SBC
  7838  b13d e930               	SBC	#'0'			; subtract "0"
  7839  b13f 38                 	SEC				; set carry for SBC
  7840  b140 e9d0               	SBC	#$D0			; subtract -"0"
  7841                          					; clear carry if byte = "0"-"9"
  7842                          LAB_2D05
  7843  b142 60                 	RTS
  7844                          
  7845                          ; page zero initialisation table $00-$12 inclusive
  7846                          
  7847                          StrTab
  7848  b143 4c                 	!text	$4C			; JMP opcode
  7849  b144 0390               	!word LAB_COLD		; initial warm start vector (cold start)
  7850                          
  7851  b146 00                 	!text	$00			; these bytes are not used by BASIC
  7852  b147 0000               	!word	$0000			; 
  7853  b149 0000               	!word	$0000			; 
  7854  b14b 0000               	!word	$0000			; 
  7855                          
  7856  b14d 4c                 	!text	$4C			; JMP opcode
  7857  b14e 409f               	!word	LAB_FCER		; initial user function vector ("Function call" error)
  7858  b150 00                 	!text	$00			; default NULL count
  7859  b151 00                 	!text	$00			; clear terminal position
  7860  b152 00                 	!text	$00			; default terminal width byte
  7861  b153 f2                 	!text	$F2			; default limit for TAB = 14
  7862  b154 0004               	!word	Ram_base		; start of user RAM
  7863                          EndTab
  7864                          
  7865                          LAB_MSZM
  7866  b156 0d0a4d656d6f7279...	!text	$0D,$0A,"Memory size ",$00
  7867                          
  7868                          LAB_SMSG
  7869  b165 200a0a202a2a2045...	!text	" ",$0A,$0A," ** EhBASIC for HBC-56 v2.22 **",$00
  7870                          
  7871                          ; numeric constants and series
  7872                          
  7873                          					; constants and series for LOG(n)
  7874                          LAB_25A0
  7875  b188 02                 	!text	$02			; counter
  7876  b189 80195662           	!text	$80,$19,$56,$62	; 0.59898
  7877  b18d 807622f3           	!text	$80,$76,$22,$F3	; 0.96147
  7878                          ;##	!text	$80,$76,$22,$F1	; 0.96147
  7879  b191 8238aa40           	!text	$82,$38,$AA,$40	; 2.88539
  7880                          ;##	!text	$82,$38,$AA,$45	; 2.88539
  7881                          
  7882                          LAB_25AD
  7883  b195 803504f3           	!text	$80,$35,$04,$F3	; 0.70711	1/root 2
  7884                          LAB_25B1
  7885  b199 813504f3           	!text	$81,$35,$04,$F3	; 1.41421	root 2
  7886                          LAB_25B5
  7887  b19d 80800000           	!text	$80,$80,$00,$00	; -0.5
  7888                          LAB_25B9
  7889  b1a1 80317218           	!text	$80,$31,$72,$18	; 0.69315	LOG(2)
  7890                          
  7891                          					; numeric PRINT constants
  7892                          LAB_2947
  7893  b1a5 91434ff8           	!text	$91,$43,$4F,$F8	; 99999.9375 (max value with at least one decimal)
  7894                          LAB_294B
  7895  b1a9 947423f7           	!text	$94,$74,$23,$F7	; 999999.4375 (max value before scientific notation)
  7896                          LAB_294F
  7897  b1ad 94742400           	!text	$94,$74,$24,$00	; 1000000
  7898                          
  7899                          					; EXP(n) constants and series
  7900                          LAB_2AFA
  7901  b1b1 8138aa3b           	!text	$81,$38,$AA,$3B	; 1.4427	(1/LOG base 2 e)
  7902                          LAB_2AFE
  7903  b1b5 06                 	!text	$06			; counter
  7904  b1b6 7463908c           	!text	$74,$63,$90,$8C	; 2.17023e-4
  7905  b1ba 77230cab           	!text	$77,$23,$0C,$AB	; 0.00124
  7906  b1be 7a1e9400           	!text	$7A,$1E,$94,$00	; 0.00968
  7907  b1c2 7c634280           	!text	$7C,$63,$42,$80	; 0.05548
  7908  b1c6 7e75fed0           	!text	$7E,$75,$FE,$D0	; 0.24023
  7909  b1ca 80317215           	!text	$80,$31,$72,$15	; 0.69315
  7910  b1ce 81000000           	!text	$81,$00,$00,$00	; 1.00000
  7911                          
  7912                          ;##	!text	$07			; counter
  7913                          ;##	!text	$74,$94,$2E,$40	; -1/7! (-1/5040)
  7914                          ;##	!text	$77,$2E,$4F,$70	;  1/6! ( 1/720)
  7915                          ;##	!text	$7A,$88,$02,$6E	; -1/5! (-1/120)
  7916                          ;##	!text	$7C,$2A,$A0,$E6	;  1/4! ( 1/24)
  7917                          ;##	!text	$7E,$AA,$AA,$50	; -1/3! (-1/6)
  7918                          ;##	!text	$7F,$7F,$FF,$FF	;  1/2! ( 1/2)
  7919                          ;##	!text	$81,$80,$00,$00	; -1/1! (-1/1)
  7920                          ;##	!text	$81,$00,$00,$00	;  1/0! ( 1/1)
  7921                          
  7922                          					; trigonometric constants and series
  7923                          LAB_2C78
  7924  b1d2 81490fdb           	!text	$81,$49,$0F,$DB	; 1.570796371 (pi/2) as floating #
  7925                          LAB_2C84
  7926  b1d6 04                 	!text	$04			; counter
  7927  b1d7 861ed7fb           	!text	$86,$1E,$D7,$FB	; 39.7109
  7928                          ;##	!text	$86,$1E,$D7,$BA	; 39.7109
  7929  b1db 87992665           	!text	$87,$99,$26,$65	;-76.575
  7930                          ;##	!text	$87,$99,$26,$64	;-76.575
  7931  b1df 87233458           	!text	$87,$23,$34,$58	; 81.6022
  7932  b1e3 86a55de1           	!text	$86,$A5,$5D,$E1	;-41.3417
  7933                          ;##	!text	$86,$A5,$5D,$E0	;-41.3417
  7934                          LAB_2C7C
  7935  b1e7 83490fdb           	!text	$83,$49,$0F,$DB	; 6.28319 (2*pi) as floating #
  7936                          ;##	!text	$83,$49,$0F,$DA	; 6.28319 (2*pi) as floating #
  7937                          
  7938                          LAB_2CC9
  7939  b1eb 08                 	!text	$08			; counter
  7940  b1ec 783ac537           	!text	$78,$3A,$C5,$37	; 0.00285
  7941  b1f0 7b83a25c           	!text	$7B,$83,$A2,$5C	;-0.0160686
  7942  b1f4 7c2edd4d           	!text	$7C,$2E,$DD,$4D	; 0.0426915
  7943  b1f8 7d99b01e           	!text	$7D,$99,$B0,$1E	;-0.0750429
  7944  b1fc 7d59ed24           	!text	$7D,$59,$ED,$24	; 0.106409
  7945  b200 7e917200           	!text	$7E,$91,$72,$00	;-0.142036
  7946  b204 7e4cb973           	!text	$7E,$4C,$B9,$73	; 0.199926
  7947  b208 7faaaa53           	!text	$7F,$AA,$AA,$53	;-0.333331
  7948                          
  7949                          ;##	!text	$08			; counter
  7950                          ;##	!text	$78,$3B,$D7,$4A	; 1/17
  7951                          ;##	!text	$7B,$84,$6E,$02	;-1/15
  7952                          ;##	!text	$7C,$2F,$C1,$FE	; 1/13
  7953                          ;##	!text	$7D,$9A,$31,$74	;-1/11
  7954                          ;##	!text	$7D,$5A,$3D,$84	; 1/9
  7955                          ;##	!text	$7E,$91,$7F,$C8	;-1/7
  7956                          ;##	!text	$7E,$4C,$BB,$E4	; 1/5
  7957                          ;##	!text	$7F,$AA,$AA,$6C	;-1/3
  7958                          
  7959                          LAB_1D96	= *+1			; $00,$00 used for undefined variables
  7960                          LAB_259C
  7961  b20c 81000000           	!text	$81,$00,$00,$00	; 1.000000, used for INC
  7962                          LAB_2AFD
  7963  b210 81800000           	!text	$81,$80,$00,$00	; -1.00000, used for DEC. must be on the same page as +1.00
  7964                          
  7965                          					; misc constants
  7966                          LAB_1DF7
  7967  b214 90                 	!text	$90			;-32768 (uses first three bytes from 0.5)
  7968                          LAB_2A96
  7969  b215 80000000           	!text	$80,$00,$00,$00	; 0.5
  7970                          LAB_2C80
  7971  b219 7f000000           	!text	$7F,$00,$00,$00	; 0.25
  7972                          LAB_26B5
  7973  b21d 84200000           	!text	$84,$20,$00,$00	; 10.0000 divide by 10 constant
  7974                          
  7975                          ; This table is used in converting numbers to ASCII.
  7976                          
  7977                          LAB_2A9A
  7978                          LAB_2A9B = LAB_2A9A+1
  7979                          LAB_2A9C = LAB_2A9B+1
  7980  b221 fe7960             	!text	$FE,$79,$60		; -100000
  7981  b224 002710             	!text	$00,$27,$10		; 10000
  7982  b227 fffc18             	!text	$FF,$FC,$18		; -1000
  7983  b22a 000064             	!text	$00,$00,$64		; 100
  7984  b22d fffff6             	!text	$FF,$FF,$F6		; -10
  7985  b230 000001             	!text	$00,$00,$01		; 1
  7986                          
  7987                          LAB_CTBL
  7988  b233 3195               	!word	LAB_END-1		; END
  7989  b235 6e94               	!word	LAB_FOR-1		; FOR
  7990  b237 7b9a               	!word	LAB_NEXT-1		; NEXT
  7991  b239 a796               	!word	LAB_DATA-1		; DATA
  7992  b23b 5d99               	!word	LAB_INPUT-1		; INPUT
  7993  b23d 759d               	!word	LAB_DIM-1		; DIM
  7994  b23f 7d99               	!word	LAB_READ-1		; READ
  7995  b241 cf97               	!word	LAB_LET-1		; LET
  7996  b243 a197               	!word	LAB_DEC-1		; DEC			new command
  7997  b245 0696               	!word	LAB_GOTO-1		; GOTO
  7998  b247 c595               	!word	LAB_RUN-1		; RUN
  7999  b249 d596               	!word	LAB_IF-1		; IF
  8000  b24b 5d95               	!word	LAB_RESTORE-1	; RESTORE		modified command
  8001  b24d e995               	!word	LAB_GOSUB-1		; GOSUB
  8002  b24f 7baf               	!word	LAB_RETIRQ-1	; RETIRQ		new command
  8003  b251 87af               	!word	LAB_RETNMI-1	; RETNMI		new command
  8004  b253 9296               	!word	LAB_RETURN-1	; RETURN
  8005  b255 3997               	!word	LAB_REM-1		; REM
  8006  b257 2f95               	!word	LAB_STOP-1		; STOP
  8007  b259 4297               	!word	LAB_ON-1		; ON			modified command
  8008  b25b 9b95               	!word	LAB_NULL-1		; NULL		modified command
  8009  b25d a497               	!word	LAB_INC-1		; INC			new command
  8010  b25f 9fa5               	!word	LAB_WAIT-1		; WAIT
  8011  b261 1bb1               	!word	V_LOAD-1		; LOAD
  8012  b263 1eb1               	!word	V_SAVE-1		; SAVE
  8013  b265 8aa0               	!word	LAB_DEF-1		; DEF
  8014  b267 24a5               	!word	LAB_POKE-1		; POKE
  8015  b269 40a5               	!word	LAB_DOKE-1		; DOKE		new command
  8016  b26b 00b1               	!word	LAB_DISPLAY-1		; DISPLAY	HBC-56 command
  8017  b26d 0bb1               	!word	LAB_PLOT-1		; PLOT		HBC-56 command
  8018  b26f 8da5               	!word	LAB_CALL-1		; CALL		new command
  8019  b271 cf95               	!word	LAB_DO-1		; DO			new command
  8020  b273 3896               	!word	LAB_LOOP-1		; LOOP		new command
  8021  b275 7098               	!word	LAB_PRINT-1		; PRINT
  8022  b277 a195               	!word	LAB_CONT-1		; CONT
  8023  b279 b993               	!word	LAB_LIST-1		; LIST
  8024  b27b b693               	!word	LAB_CLEAR-1		; CLEAR
  8025  b27d 6493               	!word	LAB_NEW-1		; NEW
  8026  b27f fcaf               	!word	LAB_WDTH-1		; WIDTH		new command
  8027  b281 3f98               	!word	LAB_GET-1		; GET			new command
  8028  b283 65a5               	!word	LAB_SWAP-1		; SWAP		new command
  8029  b285 98ad               	!word	LAB_BITSET-1	; BITSET		new command
  8030  b287 acad               	!word	LAB_BITCLR-1	; BITCLR		new command
  8031  b289 2aaf               	!word	LAB_IRQ-1		; IRQ			new command
  8032  b28b 2daf               	!word	LAB_NMI-1		; NMI			new command
  8033                          
  8034                          ; function pre process routine table
  8035                          
  8036                          LAB_FTPL
  8037                          LAB_FTPM	= LAB_FTPL+$01
  8038  b28d 7b9c               	!word	LAB_PPFN-1		; SGN(n)	process numeric expression in ()
  8039  b28f 7b9c               	!word	LAB_PPFN-1		; INT(n)		"
  8040  b291 7b9c               	!word	LAB_PPFN-1		; ABS(n)		"
  8041  b293 ff9a               	!word	LAB_EVEZ-1		; USR(x)	process any expression
  8042  b295 029c               	!word	LAB_1BF7-1		; FRE(x)		"
  8043  b297 029c               	!word	LAB_1BF7-1		; POS(x)		"
  8044  b299 7b9c               	!word	LAB_PPFN-1		; SQR(n)	process numeric expression in ()
  8045  b29b 7b9c               	!word	LAB_PPFN-1		; RND(n)		"
  8046  b29d 7b9c               	!word	LAB_PPFN-1		; LOG(n)		"
  8047  b29f 7b9c               	!word	LAB_PPFN-1		; EXP(n)		"
  8048  b2a1 7b9c               	!word	LAB_PPFN-1		; COS(n)		"
  8049  b2a3 7b9c               	!word	LAB_PPFN-1		; SIN(n)		"
  8050  b2a5 7b9c               	!word	LAB_PPFN-1		; TAN(n)		"
  8051  b2a7 7b9c               	!word	LAB_PPFN-1		; ATN(n)		"
  8052  b2a9 7b9c               	!word	LAB_PPFN-1		; PEEK(n)		"
  8053  b2ab 7b9c               	!word	LAB_PPFN-1		; DEEK(n)		"
  8054  b2ad 0000               	!word	$0000			; SADD()	none
  8055  b2af 759c               	!word	LAB_PPFS-1		; LEN($)	process string expression in ()
  8056  b2b1 7b9c               	!word	LAB_PPFN-1		; STR$(n)	process numeric expression in ()
  8057  b2b3 759c               	!word	LAB_PPFS-1		; VAL($)	process string expression in ()
  8058  b2b5 759c               	!word	LAB_PPFS-1		; ASC($)		"
  8059  b2b7 759c               	!word	LAB_PPFS-1		; UCASE$($)		"
  8060  b2b9 759c               	!word	LAB_PPFS-1		; LCASE$($)		"
  8061  b2bb 7b9c               	!word	LAB_PPFN-1		; CHR$(n)	process numeric expression in ()
  8062  b2bd a29c               	!word	LAB_BHSS-1		; HEX$(n)		"
  8063  b2bf a29c               	!word	LAB_BHSS-1		; BIN$(n)		"
  8064  b2c1 0000               	!word	$0000			; BITTST()	none
  8065  b2c3 93af               	!word	LAB_MMPP-1		; MAX()	process numeric expression
  8066  b2c5 93af               	!word	LAB_MMPP-1		; MIN()		"
  8067  b2c7 819c               	!word	LAB_PPBI-1		; PI		advance pointer
  8068  b2c9 819c               	!word	LAB_PPBI-1		; TWOPI		"
  8069  b2cb 0000               	!word	$0000			; VARPTR()	none
  8070  b2cd 869c               	!word	LAB_LRMS-1		; LEFT$()	process string expression
  8071  b2cf 869c               	!word	LAB_LRMS-1		; RIGHT$()		"
  8072  b2d1 869c               	!word	LAB_LRMS-1		; MID$()		"
  8073                          
  8074                          ; action addresses for functions
  8075                          
  8076                          LAB_FTBL
  8077                          LAB_FTBM	= LAB_FTBL+$01
  8078  b2d3 0da9               	!word	LAB_SGN-1		; SGN()
  8079  b2d5 97a9               	!word	LAB_INT-1		; INT()
  8080  b2d7 2aa9               	!word	LAB_ABS-1		; ABS()
  8081  b2d9 63ad               	!word	LAB_USR-1		; USR()
  8082  b2db 5ba0               	!word	LAB_FRE-1		; FRE()
  8083  b2dd 7aa0               	!word	LAB_POS-1		; POS()
  8084  b2df 52b0               	!word	LAB_SQR-1		; SQR()
  8085  b2e1 b3ac               	!word	LAB_RND-1		; RND()		modified function
  8086  b2e3 11a7               	!word	LAB_LOG-1		; LOG()
  8087  b2e5 15ac               	!word	LAB_EXP-1		; EXP()
  8088  b2e7 e7ac               	!word	LAB_COS-1		; COS()
  8089  b2e9 eeac               	!word	LAB_SIN-1		; SIN()
  8090  b2eb 37ad               	!word	LAB_TAN-1		; TAN()
  8091  b2ed 69ad               	!word	LAB_ATN-1		; ATN()
  8092  b2ef 19a5               	!word	LAB_PEEK-1		; PEEK()
  8093  b2f1 2da5               	!word	LAB_DEEK-1		; DEEK()		new function
  8094  b2f3 6ba4               	!word	LAB_SADD-1		; SADD()		new function
  8095  b2f5 84a4               	!word	LAB_LENS-1		; LEN()
  8096  b2f7 3ca1               	!word	LAB_STRS-1		; STR$()
  8097  b2f9 b1a4               	!word	LAB_VAL-1		; VAL()
  8098  b2fb 8fa4               	!word	LAB_ASC-1		; ASC()
  8099  b2fd 49a4               	!word	LAB_UCASE-1		; UCASE$()		new function
  8100  b2ff 28a4               	!word	LAB_LCASE-1		; LCASE$()		new function
  8101  b301 9aa3               	!word	LAB_CHRS-1		; CHR$()
  8102  b303 39ae               	!word	LAB_HEXS-1		; HEX$()		new function
  8103  b305 eaad               	!word	LAB_BINS-1		; BIN$()		new function
  8104  b307 c2ad               	!word	LAB_BTST-1		; BITTST()		new function
  8105  b309 99af               	!word	LAB_MAX-1		; MAX()		new function
  8106  b30b a9af               	!word	LAB_MIN-1		; MIN()		new function
  8107  b30d efb0               	!word	LAB_PI-1		; PI			new function
  8108  b30f f9b0               	!word	LAB_TWOPI-1		; TWOPI		new function
  8109  b311 dfb0               	!word	LAB_VARPTR-1	; VARPTR()		new function
  8110  b313 aca3               	!word	LAB_LEFT-1		; LEFT$()
  8111  b315 b5a3               	!word	LAB_RIGHT-1		; RIGHT$()
  8112  b317 e4a3               	!word	LAB_MIDS-1		; MID$()
  8113                          
  8114                          ; hierarchy and action addresses for operator
  8115                          
  8116                          LAB_OPPT
  8117  b319 79                 	!text	$79			; +
  8118  b31a d7a5               	!word	LAB_ADD-1
  8119  b31c 79                 	!text	$79			; -
  8120  b31d bca5               	!word	LAB_SUBTRACT-1
  8121  b31f 7b                 	!text	$7B			; *
  8122  b320 52a7               	!word	LAB_MULTIPLY-1
  8123  b322 7b                 	!text	$7B			; /
  8124  b323 1aa8               	!word	LAB_DIVIDE-1
  8125  b325 7f                 	!text	$7F			; ^
  8126  b326 d1ab               	!word	LAB_POWER-1
  8127  b328 50                 	!text	$50			; AND
  8128  b329 eb9c               	!word	LAB_AND-1
  8129  b32b 46                 	!text	$46			; EOR			new operator
  8130  b32c d19c               	!word	LAB_EOR-1
  8131  b32e 46                 	!text	$46			; OR
  8132  b32f de9c               	!word	LAB_OR-1
  8133  b331 56                 	!text	$56			; >>			new operator
  8134  b332 979d               	!word	LAB_RSHIFT-1
  8135  b334 56                 	!text	$56			; <<			new operator
  8136  b335 7f9d               	!word	LAB_LSHIFT-1
  8137  b337 7d                 	!text	$7D			; >
  8138  b338 0aac               	!word	LAB_GTHAN-1
  8139  b33a 5a                 	!text	$5A			; =
  8140  b33b 2d9c               	!word	LAB_EQUAL-1
  8141  b33d 64                 	!text	$64			; <
  8142  b33e 0c9d               	!word	LAB_LTHAN-1
  8143                          
  8144                          ; keywords start with ..
  8145                          ; this is the first character table and must be in alphabetic order
  8146                          
  8147                          TAB_1STC
  8148  b340 2a                 	!text	"*"
  8149  b341 2b                 	!text	"+"
  8150  b342 2d                 	!text	"-"
  8151  b343 2f                 	!text	"/"
  8152  b344 3c                 	!text	"<"
  8153  b345 3d                 	!text	"="
  8154  b346 3e                 	!text	">"
  8155  b347 3f                 	!text	"?"
  8156  b348 41                 	!text	"A"
  8157  b349 42                 	!text	"B"
  8158  b34a 43                 	!text	"C"
  8159  b34b 44                 	!text	"D"
  8160  b34c 45                 	!text	"E"
  8161  b34d 46                 	!text	"F"
  8162  b34e 47                 	!text	"G"
  8163  b34f 48                 	!text	"H"
  8164  b350 49                 	!text	"I"
  8165  b351 4c                 	!text	"L"
  8166  b352 4d                 	!text	"M"
  8167  b353 4e                 	!text	"N"
  8168  b354 4f                 	!text	"O"
  8169  b355 50                 	!text	"P"
  8170  b356 52                 	!text	"R"
  8171  b357 53                 	!text	"S"
  8172  b358 54                 	!text	"T"
  8173  b359 55                 	!text	"U"
  8174  b35a 56                 	!text	"V"
  8175  b35b 57                 	!text	"W"
  8176  b35c 5e                 	!text	"^"
  8177  b35d 00                 	!text	$00			; table terminator
  8178                          
  8179                          ; pointers to keyword tables
  8180                          
  8181                          TAB_CHRT
  8182  b35e 98b3               	!word	TAB_STAR		; table for "*"
  8183  b360 9ab3               	!word	TAB_PLUS		; table for "+"
  8184  b362 9cb3               	!word	TAB_MNUS		; table for "-"
  8185  b364 9eb3               	!word	TAB_SLAS		; table for "/"
  8186  b366 a0b3               	!word	TAB_LESS		; table for "<"
  8187  b368 a4b3               	!word	TAB_EQUL		; table for "="
  8188  b36a a6b3               	!word	TAB_MORE		; table for ">"
  8189  b36c aab3               	!word	TAB_QEST		; table for "?"
  8190  b36e acb3               	!word	TAB_ASCA		; table for "A"
  8191  b370 bcb3               	!word	TAB_ASCB		; table for "B"
  8192  b372 d5b3               	!word	TAB_ASCC		; table for "C"
  8193  b374 ecb3               	!word	TAB_ASCD		; table for "D"
  8194  b376 0cb4               	!word	TAB_ASCE		; table for "E"
  8195  b378 1bb4               	!word	TAB_ASCF		; table for "F"
  8196  b37a 25b4               	!word	TAB_ASCG		; table for "G"
  8197  b37c 32b4               	!word	TAB_ASCH		; table for "H"
  8198  b37e 38b4               	!word	TAB_ASCI		; table for "I"
  8199  b380 4ab4               	!word	TAB_ASCL		; table for "L"
  8200  b382 6fb4               	!word	TAB_ASCM		; table for "M"
  8201  b384 7db4               	!word	TAB_ASCN		; table for "N"
  8202  b386 8fb4               	!word	TAB_ASCO		; table for "O"
  8203  b388 97b4               	!word	TAB_ASCP		; table for "P"
  8204  b38a b0b4               	!word	TAB_ASCR		; table for "R"
  8205  b38c dfb4               	!word	TAB_ASCS		; table for "S"
  8206  b38e 0ab5               	!word	TAB_ASCT		; table for "T"
  8207  b390 1eb5               	!word	TAB_ASCU		; table for "U"
  8208  b392 2fb5               	!word	TAB_ASCV		; table for "V"
  8209  b394 3bb5               	!word	TAB_ASCW		; table for "W"
  8210  b396 4ab5               	!word	TAB_POWR		; table for "^"
  8211                          
  8212                          ; tables for each start character, note if a longer keyword with the same start
  8213                          ; letters as a shorter one exists then it must come first, else the list is in
  8214                          ; alphabetical order as follows ..
  8215                          
  8216                          ; [keyword,token
  8217                          ; [keyword,token]]
  8218                          ; end marker (#$00)
  8219                          
  8220                          TAB_STAR
  8221  b398 ba00               	!text TK_MUL,$00		; *
  8222                          TAB_PLUS
  8223  b39a b800               	!text TK_PLUS,$00		; +
  8224                          TAB_MNUS
  8225  b39c b900               	!text TK_MINUS,$00	; -
  8226                          TAB_SLAS
  8227  b39e bb00               	!text TK_DIV,$00		; /
  8228                          TAB_LESS
  8229                          LBB_LSHIFT
  8230  b3a0 3cc1               	!text	"<",TK_LSHIFT	; <<	note - "<<" must come before "<"
  8231  b3a2 c4                 	!text TK_LT			; <
  8232  b3a3 00                 	!text	$00
  8233                          TAB_EQUL
  8234  b3a4 c300               	!text TK_EQUAL,$00	; =
  8235                          TAB_MORE
  8236                          LBB_RSHIFT
  8237  b3a6 3ec0               	!text	">",TK_RSHIFT	; >>	note - ">>" must come before ">"
  8238  b3a8 c2                 	!text TK_GT			; >
  8239  b3a9 00                 	!text	$00
  8240                          TAB_QEST
  8241  b3aa a100               	!text TK_PRINT,$00	; ?
  8242                          TAB_ASCA
  8243                          LBB_ABS
  8244  b3ac 425328c7           	!text	"BS(",TK_ABS	; ABS(
  8245                          LBB_AND
  8246  b3b0 4e44bd             	!text	"ND",TK_AND		; AND
  8247                          LBB_ASC
  8248  b3b3 534328d9           	!text	"SC(",TK_ASC	; ASC(
  8249                          LBB_ATN
  8250  b3b7 544e28d2           	!text	"TN(",TK_ATN	; ATN(
  8251  b3bb 00                 	!text	$00
  8252                          TAB_ASCB
  8253                          LBB_BINS
  8254  b3bc 494e2428de         	!text	"IN$(",TK_BINS	; BIN$(
  8255                          LBB_BITCLR
  8256  b3c1 4954434c52aa       	!text	"ITCLR",TK_BITCLR	; BITCLR
  8257                          LBB_BITSET
  8258  b3c7 4954534554a9       	!text	"ITSET",TK_BITSET	; BITSET
  8259                          LBB_BITTST
  8260  b3cd 495454535428df     	!text	"ITTST(",TK_BITTST
  8261                          					; BITTST(
  8262  b3d4 00                 	!text	$00
  8263                          TAB_ASCC
  8264                          LBB_CALL
  8265  b3d5 414c4c9e           	!text	"ALL",TK_CALL	; CALL
  8266                          LBB_CHRS
  8267  b3d9 48522428dc         	!text	"HR$(",TK_CHRS	; CHR$(
  8268                          LBB_CLEAR
  8269  b3de 4c454152a4         	!text	"LEAR",TK_CLEAR	; CLEAR
  8270                          LBB_CONT
  8271  b3e3 4f4e54a2           	!text	"ONT",TK_CONT	; CONT
  8272                          LBB_COS
  8273  b3e7 4f5328cf           	!text	"OS(",TK_COS	; COS(
  8274  b3eb 00                 	!text	$00
  8275                          TAB_ASCD
  8276                          LBB_DATA
  8277  b3ec 41544183           	!text	"ATA",TK_DATA	; DATA
  8278                          LBB_DEC
  8279  b3f0 454388             	!text	"EC",TK_DEC		; DEC
  8280                          LBB_DEEK
  8281  b3f3 45454b28d4         	!text	"EEK(",TK_DEEK	; DEEK(
  8282                          LBB_DEF
  8283  b3f8 454699             	!text	"EF",TK_DEF		; DEF
  8284                          LBB_DIM
  8285  b3fb 494d85             	!text	"IM",TK_DIM		; DIM
  8286                          LBB_DOKE
  8287  b3fe 4f4b459b           	!text	"OKE",TK_DOKE	; DOKE note - "DOKE" must come before "DO"
  8288                          LBB_DO
  8289  b402 4f9f               	!text	"O",TK_DO		; DO
  8290                          LBB_DISPLAY
  8291  b404 4953504c41599c     	!text	"ISPLAY",TK_DISPLAY	; DISPLAY	HBC-56 command
  8292  b40b 00                 	!text	$00
  8293                          TAB_ASCE
  8294                          LBB_ELSE
  8295  b40c 4c5345ae           	!text	"LSE",TK_ELSE	; ELSE
  8296                          LBB_END
  8297  b410 4e4480             	!text	"ND",TK_END		; END
  8298                          LBB_EOR
  8299  b413 4f52be             	!text	"OR",TK_EOR		; EOR
  8300                          LBB_EXP
  8301  b416 585028ce           	!text	"XP(",TK_EXP	; EXP(
  8302  b41a 00                 	!text	$00
  8303                          TAB_ASCF
  8304                          LBB_FN
  8305  b41b 4eb0               	!text	"N",TK_FN		; FN
  8306                          LBB_FOR
  8307  b41d 4f5281             	!text	"OR",TK_FOR		; FOR
  8308                          LBB_FRE
  8309  b420 524528c9           	!text	"RE(",TK_FRE	; FRE(
  8310  b424 00                 	!text	$00
  8311                          TAB_ASCG
  8312                          LBB_GET
  8313  b425 4554a7             	!text	"ET",TK_GET		; GET
  8314                          LBB_GOSUB
  8315  b428 4f5355428d         	!text	"OSUB",TK_GOSUB	; GOSUB
  8316                          LBB_GOTO
  8317  b42d 4f544f89           	!text	"OTO",TK_GOTO	; GOTO
  8318  b431 00                 	!text	$00
  8319                          TAB_ASCH
  8320                          LBB_HEXS
  8321  b432 45582428dd         	!text	"EX$(",TK_HEXS	; HEX$(
  8322  b437 00                 	!text	$00
  8323                          TAB_ASCI
  8324                          LBB_IF
  8325  b438 468b               	!text	"F",TK_IF		; IF
  8326                          LBB_INC
  8327  b43a 4e4395             	!text	"NC",TK_INC		; INC
  8328                          LBB_INPUT
  8329  b43d 4e50555484         	!text	"NPUT",TK_INPUT	; INPUT
  8330                          LBB_INT
  8331  b442 4e5428c6           	!text	"NT(",TK_INT	; INT(
  8332                          LBB_IRQ
  8333  b446 5251ab             	!text	"RQ",TK_IRQ		; IRQ
  8334  b449 00                 	!text	$00
  8335                          TAB_ASCL
  8336                          LBB_LCASES
  8337  b44a 434153452428db     	!text	"CASE$(",TK_LCASES
  8338                          					; LCASE$(
  8339                          LBB_LEFTS
  8340  b451 4546542428e5       	!text	"EFT$(",TK_LEFTS	; LEFT$(
  8341                          LBB_LEN
  8342  b457 454e28d6           	!text	"EN(",TK_LEN	; LEN(
  8343                          LBB_LET
  8344  b45b 455487             	!text	"ET",TK_LET		; LET
  8345                          LBB_LIST
  8346  b45e 495354a3           	!text	"IST",TK_LIST	; LIST
  8347                          LBB_LOAD
  8348  b462 4f414497           	!text	"OAD",TK_LOAD	; LOAD
  8349                          LBB_LOG
  8350  b466 4f4728cd           	!text	"OG(",TK_LOG	; LOG(
  8351                          LBB_LOOP
  8352  b46a 4f4f50a0           	!text	"OOP",TK_LOOP	; LOOP
  8353  b46e 00                 	!text	$00
  8354                          TAB_ASCM
  8355                          LBB_MAX
  8356  b46f 415828e0           	!text	"AX(",TK_MAX	; MAX(
  8357                          LBB_MIDS
  8358  b473 49442428e7         	!text	"ID$(",TK_MIDS	; MID$(
  8359                          LBB_MIN
  8360  b478 494e28e1           	!text	"IN(",TK_MIN	; MIN(
  8361  b47c 00                 	!text	$00
  8362                          TAB_ASCN
  8363                          LBB_NEW
  8364  b47d 4557a5             	!text	"EW",TK_NEW		; NEW
  8365                          LBB_NEXT
  8366  b480 45585482           	!text	"EXT",TK_NEXT	; NEXT
  8367                          LBB_NMI
  8368  b484 4d49ac             	!text	"MI",TK_NMI		; NMI
  8369                          LBB_NOT
  8370  b487 4f54b3             	!text	"OT",TK_NOT		; NOT
  8371                          LBB_NULL
  8372  b48a 554c4c94           	!text	"ULL",TK_NULL	; NULL
  8373  b48e 00                 	!text	$00
  8374                          TAB_ASCO
  8375                          LBB_OFF
  8376  b48f 4646b7             	!text	"FF",TK_OFF		; OFF
  8377                          LBB_ON
  8378  b492 4e93               	!text	"N",TK_ON		; ON
  8379                          LBB_OR
  8380  b494 52bf               	!text	"R",TK_OR		; OR
  8381  b496 00                 	!text	$00
  8382                          TAB_ASCP
  8383                          LBB_PEEK
  8384  b497 45454b28d3         	!text	"EEK(",TK_PEEK	; PEEK(
  8385                          LBB_PI
  8386  b49c 49e2               	!text	"I",TK_PI		; PI
  8387                          LBB_PLOT
  8388  b49e 4c4f549d           	!text	"LOT",TK_PLOT		; PLOT
  8389                          LBB_POKE
  8390  b4a2 4f4b459a           	!text	"OKE",TK_POKE	; POKE
  8391                          LBB_POS
  8392  b4a6 4f5328ca           	!text	"OS(",TK_POS	; POS(
  8393                          LBB_PRINT
  8394  b4aa 52494e54a1         	!text	"RINT",TK_PRINT	; PRINT
  8395  b4af 00                 	!text	$00
  8396                          TAB_ASCR
  8397                          LBB_READ
  8398  b4b0 45414486           	!text	"EAD",TK_READ	; READ
  8399                          LBB_REM
  8400  b4b4 454d91             	!text	"EM",TK_REM		; REM
  8401                          LBB_RESTORE
  8402  b4b7 4553544f52458c     	!text	"ESTORE",TK_RESTORE
  8403                          					; RESTORE
  8404                          LBB_RETIRQ
  8405  b4be 45544952518e       	!text	"ETIRQ",TK_RETIRQ	; RETIRQ
  8406                          LBB_RETNMI
  8407  b4c4 45544e4d498f       	!text	"ETNMI",TK_RETNMI	; RETNMI
  8408                          LBB_RETURN
  8409  b4ca 455455524e90       	!text	"ETURN",TK_RETURN	; RETURN
  8410                          LBB_RIGHTS
  8411  b4d0 494748542428e6     	!text	"IGHT$(",TK_RIGHTS
  8412                          					; RIGHT$(
  8413                          LBB_RND
  8414  b4d7 4e4428cc           	!text	"ND(",TK_RND	; RND(
  8415                          LBB_RUN
  8416  b4db 554e8a             	!text	"UN",TK_RUN		; RUN
  8417  b4de 00                 	!text	$00
  8418                          TAB_ASCS
  8419                          LBB_SADD
  8420  b4df 41444428d5         	!text	"ADD(",TK_SADD	; SADD(
  8421                          LBB_SAVE
  8422  b4e4 41564598           	!text	"AVE",TK_SAVE	; SAVE
  8423                          LBB_SGN
  8424  b4e8 474e28c5           	!text	"GN(",TK_SGN	; SGN(
  8425                          LBB_SIN
  8426  b4ec 494e28d0           	!text	"IN(",TK_SIN	; SIN(
  8427                          LBB_SPC
  8428  b4f0 504328b1           	!text	"PC(",TK_SPC	; SPC(
  8429                          LBB_SQR
  8430  b4f4 515228cb           	!text	"QR(",TK_SQR	; SQR(
  8431                          LBB_STEP
  8432  b4f8 544550b4           	!text	"TEP",TK_STEP	; STEP
  8433                          LBB_STOP
  8434  b4fc 544f5092           	!text	"TOP",TK_STOP	; STOP
  8435                          LBB_STRS
  8436  b500 54522428d7         	!text	"TR$(",TK_STRS	; STR$(
  8437                          LBB_SWAP
  8438  b505 574150a8           	!text	"WAP",TK_SWAP	; SWAP
  8439  b509 00                 	!text	$00
  8440                          TAB_ASCT
  8441                          LBB_TAB
  8442  b50a 414228ad           	!text	"AB(",TK_TAB	; TAB(
  8443                          LBB_TAN
  8444  b50e 414e28d1           	!text	"AN(",TK_TAN	; TAN(
  8445                          LBB_THEN
  8446  b512 48454eb2           	!text	"HEN",TK_THEN	; THEN
  8447                          LBB_TO
  8448  b516 4faf               	!text	"O",TK_TO		; TO
  8449                          LBB_TWOPI
  8450  b518 574f5049e3         	!text	"WOPI",TK_TWOPI	; TWOPI
  8451  b51d 00                 	!text	$00
  8452                          TAB_ASCU
  8453                          LBB_UCASES
  8454  b51e 434153452428da     	!text	"CASE$(",TK_UCASES
  8455                          					; UCASE$(
  8456                          LBB_UNTIL
  8457  b525 4e54494cb5         	!text	"NTIL",TK_UNTIL	; UNTIL
  8458                          LBB_USR
  8459  b52a 535228c8           	!text	"SR(",TK_USR	; USR(
  8460  b52e 00                 	!text	$00
  8461                          TAB_ASCV
  8462                          LBB_VAL
  8463  b52f 414c28d8           	!text	"AL(",TK_VAL	; VAL(
  8464                          LBB_VPTR
  8465  b533 415250545228e4     	!text	"ARPTR(",TK_VPTR	; VARPTR(
  8466  b53a 00                 	!text	$00
  8467                          TAB_ASCW
  8468                          LBB_WAIT
  8469  b53b 41495496           	!text	"AIT",TK_WAIT	; WAIT
  8470                          LBB_WHILE
  8471  b53f 48494c45b6         	!text	"HILE",TK_WHILE	; WHILE
  8472                          LBB_WIDTH
  8473  b544 49445448a6         	!text	"IDTH",TK_WIDTH	; WIDTH
  8474  b549 00                 	!text	$00
  8475                          TAB_POWR
  8476  b54a bc00               	!text	TK_POWER,$00	; ^
  8477                          
  8478                          ; new decode table for LIST
  8479                          ; Table is ..
  8480                          ; byte - keyword length, keyword first character
  8481                          ; word - pointer to rest of keyword from dictionary
  8482                          
  8483                          ; note if length is 1 then the pointer is ignored
  8484                          
  8485                          LAB_KEYT
  8486  b54c 0345               	!text	3,'E'
  8487  b54e 10b4               	!word	LBB_END		; END
  8488  b550 0346               	!text	3,'F'
  8489  b552 1db4               	!word	LBB_FOR		; FOR
  8490  b554 044e               	!text	4,'N'
  8491  b556 80b4               	!word	LBB_NEXT		; NEXT
  8492  b558 0444               	!text	4,'D'
  8493  b55a ecb3               	!word	LBB_DATA		; DATA
  8494  b55c 0549               	!text	5,'I'
  8495  b55e 3db4               	!word	LBB_INPUT		; INPUT
  8496  b560 0344               	!text	3,'D'
  8497  b562 fbb3               	!word	LBB_DIM		; DIM
  8498  b564 0452               	!text	4,'R'
  8499  b566 b0b4               	!word	LBB_READ		; READ
  8500  b568 034c               	!text	3,'L'
  8501  b56a 5bb4               	!word	LBB_LET		; LET
  8502  b56c 0344               	!text	3,'D'
  8503  b56e f0b3               	!word	LBB_DEC		; DEC
  8504  b570 0447               	!text	4,'G'
  8505  b572 2db4               	!word	LBB_GOTO		; GOTO
  8506  b574 0352               	!text	3,'R'
  8507  b576 dbb4               	!word	LBB_RUN		; RUN
  8508  b578 0249               	!text	2,'I'
  8509  b57a 38b4               	!word	LBB_IF		; IF
  8510  b57c 0752               	!text	7,'R'
  8511  b57e b7b4               	!word	LBB_RESTORE		; RESTORE
  8512  b580 0547               	!text	5,'G'
  8513  b582 28b4               	!word	LBB_GOSUB		; GOSUB
  8514  b584 0652               	!text	6,'R'
  8515  b586 beb4               	!word	LBB_RETIRQ		; RETIRQ
  8516  b588 0652               	!text	6,'R'
  8517  b58a c4b4               	!word	LBB_RETNMI		; RETNMI
  8518  b58c 0652               	!text	6,'R'
  8519  b58e cab4               	!word	LBB_RETURN		; RETURN
  8520  b590 0352               	!text	3,'R'
  8521  b592 b4b4               	!word	LBB_REM		; REM
  8522  b594 0453               	!text	4,'S'
  8523  b596 fcb4               	!word	LBB_STOP		; STOP
  8524  b598 024f               	!text	2,'O'
  8525  b59a 92b4               	!word	LBB_ON		; ON
  8526  b59c 044e               	!text	4,'N'
  8527  b59e 8ab4               	!word	LBB_NULL		; NULL
  8528  b5a0 0349               	!text	3,'I'
  8529  b5a2 3ab4               	!word	LBB_INC		; INC
  8530  b5a4 0457               	!text	4,'W'
  8531  b5a6 3bb5               	!word	LBB_WAIT		; WAIT
  8532  b5a8 044c               	!text	4,'L'
  8533  b5aa 62b4               	!word	LBB_LOAD		; LOAD
  8534  b5ac 0453               	!text	4,'S'
  8535  b5ae e4b4               	!word	LBB_SAVE		; SAVE
  8536  b5b0 0344               	!text	3,'D'
  8537  b5b2 f8b3               	!word	LBB_DEF		; DEF
  8538  b5b4 0450               	!text	4,'P'
  8539  b5b6 a2b4               	!word	LBB_POKE		; POKE
  8540  b5b8 0444               	!text	4,'D'
  8541  b5ba feb3               	!word	LBB_DOKE		; DOKE
  8542  b5bc 0744               	!text	7,'D'
  8543  b5be 04b4               	!word	LBB_DISPLAY		; DISPLAY
  8544  b5c0 0450               	!text	4,'P'
  8545  b5c2 9eb4               	!word	LBB_PLOT		; PLOT
  8546  b5c4 0443               	!text	4,'C'
  8547  b5c6 d5b3               	!word	LBB_CALL		; CALL
  8548  b5c8 0244               	!text	2,'D'
  8549  b5ca 02b4               	!word	LBB_DO		; DO
  8550  b5cc 044c               	!text	4,'L'
  8551  b5ce 6ab4               	!word	LBB_LOOP		; LOOP
  8552  b5d0 0550               	!text	5,'P'
  8553  b5d2 aab4               	!word	LBB_PRINT		; PRINT
  8554  b5d4 0443               	!text	4,'C'
  8555  b5d6 e3b3               	!word	LBB_CONT		; CONT
  8556  b5d8 044c               	!text	4,'L'
  8557  b5da 5eb4               	!word	LBB_LIST		; LIST
  8558  b5dc 0543               	!text	5,'C'
  8559  b5de deb3               	!word	LBB_CLEAR		; CLEAR
  8560  b5e0 034e               	!text	3,'N'
  8561  b5e2 7db4               	!word	LBB_NEW		; NEW
  8562  b5e4 0557               	!text	5,'W'
  8563  b5e6 44b5               	!word	LBB_WIDTH		; WIDTH
  8564  b5e8 0347               	!text	3,'G'
  8565  b5ea 25b4               	!word	LBB_GET		; GET
  8566  b5ec 0453               	!text	4,'S'
  8567  b5ee 05b5               	!word	LBB_SWAP		; SWAP
  8568  b5f0 0642               	!text	6,'B'
  8569  b5f2 c7b3               	!word	LBB_BITSET		; BITSET
  8570  b5f4 0642               	!text	6,'B'
  8571  b5f6 c1b3               	!word	LBB_BITCLR		; BITCLR
  8572  b5f8 0349               	!text	3,'I'
  8573  b5fa 46b4               	!word	LBB_IRQ		; IRQ
  8574  b5fc 034e               	!text	3,'N'
  8575  b5fe 84b4               	!word	LBB_NMI		; NMI
  8576                          
  8577                          ; secondary commands (can't start a statement)
  8578                          
  8579  b600 0454               	!text	4,'T'
  8580  b602 0ab5               	!word	LBB_TAB		; TAB
  8581  b604 0445               	!text	4,'E'
  8582  b606 0cb4               	!word	LBB_ELSE		; ELSE
  8583  b608 0254               	!text	2,'T'
  8584  b60a 16b5               	!word	LBB_TO		; TO
  8585  b60c 0246               	!text	2,'F'
  8586  b60e 1bb4               	!word	LBB_FN		; FN
  8587  b610 0453               	!text	4,'S'
  8588  b612 f0b4               	!word	LBB_SPC		; SPC
  8589  b614 0454               	!text	4,'T'
  8590  b616 12b5               	!word	LBB_THEN		; THEN
  8591  b618 034e               	!text	3,'N'
  8592  b61a 87b4               	!word	LBB_NOT		; NOT
  8593  b61c 0453               	!text	4,'S'
  8594  b61e f8b4               	!word	LBB_STEP		; STEP
  8595  b620 0555               	!text	5,'U'
  8596  b622 25b5               	!word	LBB_UNTIL		; UNTIL
  8597  b624 0557               	!text	5,'W'
  8598  b626 3fb5               	!word	LBB_WHILE		; WHILE
  8599  b628 034f               	!text	3,'O'
  8600  b62a 8fb4               	!word	LBB_OFF		; OFF
  8601                          
  8602                          ; opperators
  8603                          
  8604  b62c 012b               	!text	1,'+'
  8605  b62e 0000               	!word	$0000			; +
  8606  b630 012d               	!text	1,'-'
  8607  b632 0000               	!word	$0000			; -
  8608  b634 012a               	!text	1,'*'
  8609  b636 0000               	!word	$0000			; *
  8610  b638 012f               	!text	1,'/'
  8611  b63a 0000               	!word	$0000			; /
  8612  b63c 015e               	!text	1,'^'
  8613  b63e 0000               	!word	$0000			; ^
  8614  b640 0341               	!text	3,'A'
  8615  b642 b0b3               	!word	LBB_AND		; AND
  8616  b644 0345               	!text	3,'E'
  8617  b646 13b4               	!word	LBB_EOR		; EOR
  8618  b648 024f               	!text	2,'O'
  8619  b64a 94b4               	!word	LBB_OR		; OR
  8620  b64c 023e               	!text	2,'>'
  8621  b64e a6b3               	!word	LBB_RSHIFT		; >>
  8622  b650 023c               	!text	2,'<'
  8623  b652 a0b3               	!word	LBB_LSHIFT		; <<
  8624  b654 013e               	!text	1,'>'
  8625  b656 0000               	!word	$0000			; >
  8626  b658 013d               	!text	1,'='
  8627  b65a 0000               	!word	$0000			; =
  8628  b65c 013c               	!text	1,'<'
  8629  b65e 0000               	!word	$0000			; <
  8630                          
  8631                          ; functions
  8632                          
  8633  b660 0453               	!text	4,'S'			;
  8634  b662 e8b4               	!word	LBB_SGN		; SGN
  8635  b664 0449               	!text	4,'I'			;
  8636  b666 42b4               	!word	LBB_INT		; INT
  8637  b668 0441               	!text	4,'A'			;
  8638  b66a acb3               	!word	LBB_ABS		; ABS
  8639  b66c 0455               	!text	4,'U'			;
  8640  b66e 2ab5               	!word	LBB_USR		; USR
  8641  b670 0446               	!text	4,'F'			;
  8642  b672 20b4               	!word	LBB_FRE		; FRE
  8643  b674 0450               	!text	4,'P'			;
  8644  b676 a6b4               	!word	LBB_POS		; POS
  8645  b678 0453               	!text	4,'S'			;
  8646  b67a f4b4               	!word	LBB_SQR		; SQR
  8647  b67c 0452               	!text	4,'R'			;
  8648  b67e d7b4               	!word	LBB_RND		; RND
  8649  b680 044c               	!text	4,'L'			;
  8650  b682 66b4               	!word	LBB_LOG		; LOG
  8651  b684 0445               	!text	4,'E'			;
  8652  b686 16b4               	!word	LBB_EXP		; EXP
  8653  b688 0443               	!text	4,'C'			;
  8654  b68a e7b3               	!word	LBB_COS		; COS
  8655  b68c 0453               	!text	4,'S'			;
  8656  b68e ecb4               	!word	LBB_SIN		; SIN
  8657  b690 0454               	!text	4,'T'			;
  8658  b692 0eb5               	!word	LBB_TAN		; TAN
  8659  b694 0441               	!text	4,'A'			;
  8660  b696 b7b3               	!word	LBB_ATN		; ATN
  8661  b698 0550               	!text	5,'P'			;
  8662  b69a 97b4               	!word	LBB_PEEK		; PEEK
  8663  b69c 0544               	!text	5,'D'			;
  8664  b69e f3b3               	!word	LBB_DEEK		; DEEK
  8665  b6a0 0553               	!text	5,'S'			;
  8666  b6a2 dfb4               	!word	LBB_SADD		; SADD
  8667  b6a4 044c               	!text	4,'L'			;
  8668  b6a6 57b4               	!word	LBB_LEN		; LEN
  8669  b6a8 0553               	!text	5,'S'			;
  8670  b6aa 00b5               	!word	LBB_STRS		; STR$
  8671  b6ac 0456               	!text	4,'V'			;
  8672  b6ae 2fb5               	!word	LBB_VAL		; VAL
  8673  b6b0 0441               	!text	4,'A'			;
  8674  b6b2 b3b3               	!word	LBB_ASC		; ASC
  8675  b6b4 0755               	!text	7,'U'			;
  8676  b6b6 1eb5               	!word	LBB_UCASES		; UCASE$
  8677  b6b8 074c               	!text	7,'L'			;
  8678  b6ba 4ab4               	!word	LBB_LCASES		; LCASE$
  8679  b6bc 0543               	!text	5,'C'			;
  8680  b6be d9b3               	!word	LBB_CHRS		; CHR$
  8681  b6c0 0548               	!text	5,'H'			;
  8682  b6c2 32b4               	!word	LBB_HEXS		; HEX$
  8683  b6c4 0542               	!text	5,'B'			;
  8684  b6c6 bcb3               	!word	LBB_BINS		; BIN$
  8685  b6c8 0742               	!text	7,'B'			;
  8686  b6ca cdb3               	!word	LBB_BITTST		; BITTST
  8687  b6cc 044d               	!text	4,'M'			;
  8688  b6ce 6fb4               	!word	LBB_MAX		; MAX
  8689  b6d0 044d               	!text	4,'M'			;
  8690  b6d2 78b4               	!word	LBB_MIN		; MIN
  8691  b6d4 0250               	!text	2,'P'			;
  8692  b6d6 9cb4               	!word	LBB_PI		; PI
  8693  b6d8 0554               	!text	5,'T'			;
  8694  b6da 18b5               	!word	LBB_TWOPI		; TWOPI
  8695  b6dc 0756               	!text	7,'V'			;
  8696  b6de 33b5               	!word	LBB_VPTR		; VARPTR
  8697  b6e0 064c               	!text	6,'L'			;
  8698  b6e2 51b4               	!word	LBB_LEFTS		; LEFT$
  8699  b6e4 0752               	!text	7,'R'			;
  8700  b6e6 d0b4               	!word	LBB_RIGHTS		; RIGHT$
  8701  b6e8 054d               	!text	5,'M'			;
  8702  b6ea 73b4               	!word	LBB_MIDS		; MID$
  8703                          
  8704                          ; BASIC messages, mostly error messages
  8705                          
  8706                          LAB_BAER
  8707  b6ec 10b7               	!word	ERR_NF		;$00 NEXT without FOR
  8708  b6ee 22b7               	!word	ERR_SN		;$02 syntax
  8709  b6f0 2ab7               	!word	ERR_RG		;$04 RETURN without GOSUB
  8710  b6f2 40b7               	!word	ERR_OD		;$06 out of data
  8711  b6f4 4db7               	!word	ERR_FC		;$08 function call
  8712  b6f6 5cb7               	!word	ERR_OV		;$0A overflow
  8713  b6f8 66b7               	!word	ERR_OM		;$0C out of memory
  8714  b6fa 75b7               	!word	ERR_US		;$0E undefined statement
  8715  b6fc 8ab7               	!word	ERR_BS		;$10 array bounds
  8716  b6fe 98b7               	!word	ERR_DD		;$12 double dimension array
  8717  b700 aab7               	!word	ERR_D0		;$14 divide by 0
  8718  b702 bab7               	!word	ERR_ID		;$16 illegal direct
  8719  b704 cab7               	!word	ERR_TM		;$18 type mismatch
  8720  b706 d9b7               	!word	ERR_LS		;$1A long string
  8721  b708 eab7               	!word	ERR_ST		;$1C string too complex
  8722  b70a feb7               	!word	ERR_CN		;$1E continue error
  8723  b70c 0eb8               	!word	ERR_UF		;$20 undefined function
  8724  b70e 22b8               	!word ERR_LD		;$22 LOOP without DO
  8725                          
  8726                          ; I may implement these two errors to force definition of variables and
  8727                          ; dimensioning of arrays before use.
  8728                          
  8729                          ;	!word ERR_UV		;$24 undefined variable
  8730                          
  8731                          ; the above error has been tested and works (see code and comments below LAB_1D8B)
  8732                          
  8733                          ;	!word ERR_UA		;$26 undimensioned array
  8734                          
  8735  b710 204e455854207769...ERR_NF	!text	" NEXT without FOR",$00
  8736  b722 2053796e74617800   ERR_SN	!text	" Syntax",$00
  8737  b72a 2052455455524e20...ERR_RG	!text	" RETURN without GOSUB",$00
  8738  b740 204f7574206f6620...ERR_OD	!text	" Out of DATA",$00
  8739  b74d 2046756e6374696f...ERR_FC	!text	" Function call",$00
  8740  b75c 204f766572666c6f...ERR_OV	!text	" Overflow",$00
  8741  b766 204f7574206f6620...ERR_OM	!text	" Out of memory",$00
  8742  b775 20556e646566696e...ERR_US	!text	" Undefined statement",$00
  8743  b78a 2041727261792062...ERR_BS	!text	" Array bounds",$00
  8744  b798 20446f75626c6520...ERR_DD	!text	" Double dimension",$00
  8745  b7aa 2044697669646520...ERR_D0	!text	" Divide by zero",$00
  8746  b7ba 20496c6c6567616c...ERR_ID	!text	" Illegal direct",$00
  8747  b7ca 2054797065206d69...ERR_TM	!text	" Type mismatch",$00
  8748  b7d9 20537472696e6720...ERR_LS	!text	" String too long",$00
  8749  b7ea 20537472696e6720...ERR_ST	!text	" String too complex",$00
  8750  b7fe 2043616e27742063...ERR_CN	!text	" Can't continue",$00
  8751  b80e 20556e646566696e...ERR_UF	!text	" Undefined function",$00
  8752  b822 204c4f4f50207769...ERR_LD	!text	" LOOP without DO",$00
  8753                          
  8754                          ;ERR_UV	!text	"Undefined variable",$00
  8755                          
  8756                          ; the above error has been tested and works (see code and comments below LAB_1D8B)
  8757                          
  8758                          ;ERR_UA	!text	"Undimensioned array",$00
  8759                          
  8760  b833 07427265616b00     LAB_BMSG	!text	$07, "Break",$00
  8761  b83a 07204572726f7200   LAB_EMSG	!text	$07, " Error",$00
  8762  b842 20696e206c696e65...LAB_LMSG	!text	" in line ",$00
  8763  b84c 0a0a205265616479...LAB_RMSG	!text	$0A,$0A," Ready",$0A,$0A,$00
  8764                          
  8765  b857 2045787472612069...LAB_IMSG	!text	" Extra ignored",$0D,$0A,$00
  8766  b868 205265646f206672...LAB_REDO	!text	" Redo from start",$0D,$0A,$00
  8767                          

; ******** Source: basic_hbc56_core.asm
    12                                 ; EhBASIC
    13                          
    14                          ; For saving registers
    15                          SAVE_X          = HBC56_USER_ZP_START
    16                          SAVE_Y          = HBC56_USER_ZP_START + 1
    17                          SAVE_A          = HBC56_USER_ZP_START + 2
    18                          
    19                          BASIC_XPOS = HBC56_USER_ZP_START + 4
    20                          BASIC_YPOS = HBC56_USER_ZP_START + 5
    21                          BASIC_COLOR = HBC56_USER_ZP_START + 6
    22                          
    23                          ; put the IRQ and NMI code in RAM so that it can be changed
    24                          IRQ_vec         = VEC_SV+2      ; IRQ code vector
    25                          NMI_vec         = IRQ_vec+$0A   ; NMI code vector
    26                          
    27                          ; -----------------------------------------------------------------------------
    28                          ; main entry point
    29                          ; -----------------------------------------------------------------------------
    30                          hbc56Main:
    31                          RES_vec:
    32  b87b 2025c9                     jsr hbc56SetupDisplay
    33                          
    34                                  ; copy I/O vectors
    35  b87e a009                       ldy #END_CODE - LAB_vec - 1    ; set index/count
    36                          LAB_stlp
    37  b880 b98fb8                     lda LAB_vec, Y         ; get byte from interrupt code
    38  b883 990303                     sta VEC_CC, Y            ; save to RAM
    39  b886 88                         dey
    40  b887 10f7                       bpl LAB_stlp
    41                          
    42  b889 58                         cli                        ; enable interrupts
    43                          
    44  b88a 4c0390                     jmp LAB_COLD
    45                          
    46                          ; -----------------------------------------------------------------------------
    47                          ; hybc56Load - EhBASIC load subroutine (for HBC-56)   (TBA)
    48                          ; -----------------------------------------------------------------------------
    49                          hbc56Load
    50  b88d 60                         rts
    51                          
    52                          ; -----------------------------------------------------------------------------
    53                          ; hybc56Save - EhBASIC save subroutine (for HBC-56)   (TBA)
    54                          ; -----------------------------------------------------------------------------
    55                          hbc56Save
    56  b88e 60                         rts
    57                          
    58                          ; -----------------------------------------------------------------------------
    59                          ; vector table - gets copied to VEC_IN in RAM
    60                          ; -----------------------------------------------------------------------------
    61                          LAB_vec
    62  b88f 0fc0                   !word    hbc56In         ; check for break (Ctrl+C)
    63  b891 0fc0                   !word    hbc56In            ; byte in from keyboard
    64  b893 6cc9                   !word    hbc56Out           ; byte out to screen
    65  b895 8db8                   !word    hbc56Load          ; load vector for EhBASIC
    66  b897 8eb8                   !word    hbc56Save          ; save vector for EhBASIC
    67                          
    68                          END_CODE        ; so we know when to stop copying

; ******** Source: basic_glcd.asm
    10                                      ; core basic

; ******** Source: functions\basic_functions.asm
     1                          ; Troy's HBC-56 - Custom BASIC functions
     2                          ;
     3                          ; Copyright (c) 2022 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          
    10                          ; CALL COLOR,$ab 
    11                          
    12                          basicColor:
    13  b899 20f5a4                     jsr  LAB_SCGB
    14  b89c 8a                         txa
    15  b89d 853e                       sta BASIC_COLOR
    16  b89f 4c56e7                     jmp tmsInitColorTable
    17                          
    18                          basicCls:
    19  b8a2 2039e7                     jsr tmsInitTextTable
    20  b8a5 4ce1e8                     jmp tmsConsoleHome
    21                          
    22                          modeTable:
    23  b8a8 44e610e6aeb8       !word tmsModeText,tmsModeGraphicsI,tmsModeII
    24                          
    25                          tmsModeII:
    26  b8ae 08                         php
    27  b8af 78                         sei
    28                                          ; clear the name table
    29  b8b0 0878a9008d117f20...        +tmsSetAddrNameTable
    30  b8c3 a003                       ldy #3
    31  b8c5 a900                       lda #0
    32                          -
    33  b8c7 8d107f2079e5               +tmsPut
    34  b8cd 1a                         inc
    35  b8ce d0f7                       bne -
    36  b8d0 88                         dey
    37  b8d1 d0f4                       bne -
    38                          
    39                                  ; set all color table entries to transparent
    40  b8d3 0878a9008d117f20...        +tmsSetAddrColorTable
    41  b8e6 a9f1                       +tmsColorFgBg TMS_WHITE, TMS_BLACK
    42  b8e8 853e                       sta BASIC_COLOR
    43  b8ea 20a7e6                     jsr _tmsSendKb
    44  b8ed 20a7e6                     jsr _tmsSendKb
    45  b8f0 20a7e6                     jsr _tmsSendKb
    46  b8f3 20a7e6                     jsr _tmsSendKb
    47  b8f6 20a7e6                     jsr _tmsSendKb
    48  b8f9 20a7e6                     jsr _tmsSendKb        
    49                          
    50                                  ; clear the pattern table
    51  b8fc 0878a9008d117f20...        +tmsSetAddrPattTable
    52  b90f a900                       lda #0
    53  b911 20a7e6                     jsr _tmsSendKb
    54  b914 20a7e6                     jsr _tmsSendKb
    55  b917 20a7e6                     jsr _tmsSendKb
    56  b91a 20a7e6                     jsr _tmsSendKb
    57  b91d 20a7e6                     jsr _tmsSendKb
    58  b920 20a7e6                     jsr _tmsSendKb
    59                          
    60  b923 28                         plp
    61  b924 4c23e6                     jmp tmsModeGraphicsII
    62                          
    63                          
    64                          basicMode:
    65  b927 08                         php
    66  b928 78                         sei
    67                          
    68  b929 20a2b8                     jsr basicCls
    69  b92c 20f5a4                     jsr  LAB_SCGB
    70  b92f 8a                         txa
    71  b930 c903                       cmp #03
    72  b932 b013                       bcs basicErrorHandler
    73  b934 0a                         asl
    74  b935 aa                         tax
    75  b936 28                         plp
    76  b937 7ca8b8                     jmp (modeTable,x)
    77                          
    78                          basicMode2:
    79  b93a 08                         php
    80  b93b 78                         sei
    81                          
    82  b93c 8a                         txa
    83  b93d c903                       cmp #03
    84  b93f b006                       bcs basicErrorHandler
    85  b941 0a                         asl
    86  b942 aa                         tax
    87  b943 28                         plp
    88  b944 7ca8b8                     jmp (modeTable,x)
    89                          
    90                          
    91                          basicErrorHandler:
    92  b947 28                         plp
    93  b948 4c409f                     JMP  LAB_FCER
    94                          
    95                          doPlot:
    96  b94b 863c                       stx BASIC_XPOS
    97  b94d 843d                       sty BASIC_YPOS
    98                                  ;lda #192
    99                                  ;cmp BASIC_YPOS
   100                                  ;bcc +
   101                                  ;rts
   102                          +
   103                          
   104                          
   105  b94f 08                         php
   106  b950 78                         sei
   107                          
   108  b951 200ae9                     jsr tmsSetPatternTmpAddressII
   109  b954 20a8e5                     jsr tmsSetAddressRead
   110  b957 a53c                       lda BASIC_XPOS
   111  b959 2907                       and #$07
   112  b95b aa                         tax
   113  b95c ad107f2079e5               +tmsGet
   114  b962 1d30e1                     ora tableBitFromLeft, x
   115  b965 48                         pha
   116  b966 2092e5                     jsr tmsSetAddressWrite
   117  b969 68                         pla
   118  b96a 8d107f2079e5               +tmsPut
   119                          
   120                                  ; cell color
   121  b970 a63c                       ldx BASIC_XPOS  
   122  b972 a43d                       ldy BASIC_YPOS
   123  b974 2006e9                     jsr tmsSetColorTmpAddressII
   124  b977 2092e5                     jsr tmsSetAddressWrite
   125  b97a a53e                       lda BASIC_COLOR
   126  b97c 8d107f2079e5               +tmsPut
   127                          
   128  b982 28                         plp
   129  b983 60                         rts
   130                          
   131                          basicSetPixel
   132  b984 20f5a4                     jsr  LAB_SCGB
   133  b987 863c                       stx BASIC_XPOS
   134  b989 20f5a4                     jsr  LAB_SCGB
   135  b98c 863d                       stx BASIC_YPOS
   136                          
   137  b98e a63c                       ldx BASIC_XPOS
   138  b990 a43d                       ldy BASIC_YPOS
   139                          
   140  b992 80b7                       bra doPlot
   141                          
   142                          basicClearPixel
   143  b994 48                         pha
   144  b995 da                         phx
   145  b996 5a                         phy
   146  b997 08                         php
   147  b998 78                         sei
   148                          
   149  b999 20f5a4                     jsr  LAB_SCGB
   150  b99c 863c                       stx BASIC_XPOS
   151  b99e 20f5a4                     jsr  LAB_SCGB
   152  b9a1 863d                       stx BASIC_YPOS
   153                          
   154  b9a3 a63c                       ldx BASIC_XPOS
   155  b9a5 a43d                       ldy BASIC_YPOS
   156  b9a7 200ae9                     jsr tmsSetPatternTmpAddressII
   157  b9aa 20a8e5                     jsr tmsSetAddressRead
   158  b9ad a53c                       lda BASIC_XPOS
   159  b9af 2907                       and #$07
   160  b9b1 aa                         tax
   161  b9b2 ad107f2079e5               +tmsGet
   162  b9b8 3d38e1                     and tableInvBitFromLeft, x
   163  b9bb 48                         pha
   164  b9bc 2092e5                     jsr tmsSetAddressWrite
   165  b9bf 68                         pla
   166  b9c0 8d107f2079e5               +tmsPut
   167  b9c6 28                         plp
   168  b9c7 7a                         ply
   169  b9c8 fa                         plx
   170  b9c9 68                         pla
   171                          
   172  b9ca 60                         rts
   173                          
   174                          
   175                          *=$c000
   176                          
   177                          PAL: ; $c000
   178  c000 4c99b8                     jmp basicColor   
   179                          CLS: ; $c003
   180  c003 4ca2b8                     jmp basicCls
   181                          MODE: ; $c006
   182  c006 4c27b9                     jmp basicMode
   183                          SETPIXEL: ; $c009
   184  c009 4c84b9                     jmp basicSetPixel
   185                          CLEARPIXEL: ; $c00c
   186  c00c 4c94b9                     jmp basicClearPixel

; ******** Source: basic_glcd.asm
    11                             ; custom functions
    12                          

; ******** Source: drivers\input.asm
     1                          ; Troy's HBC-56 - BASIC - Input
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          
    10                          
    11                          ; -----------------------------------------------------------------------------
    12                          ; hbc56In - EhBASIC input subroutine (for HBC-56) - must not block
    13                          ; -----------------------------------------------------------------------------
    14                          ; Outputs:      A - ASCII character captured from keyboard
    15                          ;               C - Flag set if key captured, clear if no key pressed
    16                          ; -----------------------------------------------------------------------------
    17                          hbc56In
    18  c00f da                         phx
    19                          
    20  c010 a221                       ldx #$21        ; check ctrl+c
    21  c012 208ef3                     jsr kbIsPressed
    22  c015 f00f                       beq @notPressed
    23  c017 a214                       ldx #$14
    24  c019 208ef3                     jsr kbIsPressed
    25  c01c f008                       beq @notPressed
    26  c01e fa                         plx
    27  c01f 2028f4                     jsr kbReadAscii
    28  c022 a903                       lda #$03
    29  c024 38                         sec
    30  c025 60                         rts
    31                          @notPressed
    32  c026 fa                         plx
    33                          
    34  c027 2028f4                     jsr kbReadAscii ; HBC-56 keyboard routine can be used directly
    35                                                  ; we could just use it directly in the vector 
    36                                                  ; table, but it's here for clarity
    37  c02a 60                         rts

; ******** Source: basic_glcd.asm
    13                                                 ; input routines

; ******** Source: drivers\output_lcd_12864.asm
     1                          ; Troy's HBC-56 - BASIC - Output (128x64 Graphics LCD)
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          
    10                          
    11                          TILE_OFFSET = HBC56_USER_ZP_START + 3
    12                          
    13  c02b eaeaeaeaeaeaeaea...!align 255, 0
    14                          c64FontData:
    15  c100 0000000000000000...	!bin "lcd/fonts/c64-font-ascii.bin"
    16                          
    17                          onVsync:
    18  c900 adc97c                     lda HBC56_TICKS
    19  c903 f005                       beq .doCursor
    20  c905 c91e                       cmp #30
    21  c907 f001                       beq .doCursor
    22  c909 60                         rts
    23                          
    24                          .doCursor:
    25  c90a adc97c                     lda HBC56_TICKS
    26  c90d f005                       beq +
    27  c90f a920                       lda #' '
    28  c911 4c16c9                     jmp ++
    29                          + 
    30  c914 a9ff                       lda #$ff
    31                          ++
    32                          
    33  c916 8ccf7c                     sty HBC56_TMP_Y
    34  c919 a43b                       ldy TILE_OFFSET
    35  c91b 99007a                     sta TILEMAP_DEFAULT_BUFFER_ADDRESS, y
    36  c91e accf7c                     ldy HBC56_TMP_Y
    37  c921 2013f1                     jsr tilemapRenderToLcd
    38                          
    39  c924 60                         rts
    40                          
    41                          ; -----------------------------------------------------------------------------
    42                          ; hbc56SetupDisplay - Setup the display (LCD)
    43                          ; -----------------------------------------------------------------------------
    44                          hbc56SetupDisplay:
    45                          
    46  c925 78                         sei
    47                          
    48  c926 206eed             	jsr lcdInit
    49  c929 2080ed             	jsr lcdClear
    50  c92c 20aaec             	jsr lcdGraphicsMode
    51                          
    52  c92f a9008518a97b8519...	+tilemapCreateDefault (TILEMAP_SIZE_X_16 | TILEMAP_SIZE_Y_8), c64FontData
    53                          
    54  c958 a900                       lda #0
    55  c95a 853b                       sta TILE_OFFSET
    56                          
    57                          !ifdef tmsInit {
    58  c95c a9008de37ca9c98d...        +hbc56SetVsyncCallback onVsync
    59  c966 a92020e5e5                 +tmsEnableInterrupts
    60                          }
    61                          
    62  c96b 60                         rts
    63                          
    64                          ; -----------------------------------------------------------------------------
    65                          ; hbc56Out - EhBASIC output subroutine (for HBC-56 LCD)
    66                          ; -----------------------------------------------------------------------------
    67                          ; Inputs:       A - ASCII character (or code) to output
    68                          ; Outputs:      A - must be maintained
    69                          ; -----------------------------------------------------------------------------
    70                          hbc56Out:
    71  c96c 78                         sei     ; disable interrupts during output
    72  c96d 8638                       stx SAVE_X
    73  c96f 8439                       sty SAVE_Y
    74  c971 853a                       sta SAVE_A
    75  c973 c90a                       cmp #ASCII_RETURN
    76  c975 f02e                       beq .newline
    77  c977 c908                       cmp #ASCII_BACKSPACE
    78  c979 f04a                       beq .backspace
    79                          
    80  c97b c907                       cmp #ASCII_BELL ; bell (end of buffer)
    81  c97d f020                       beq .bellOut
    82                          
    83  c97f c90d                       cmp #ASCII_CR   ; omit these
    84  c981 f00a                       beq .endOut
    85                          
    86                                  ; regular character
    87  c983 a43b                       ldy TILE_OFFSET
    88  c985 99007a                     sta TILEMAP_DEFAULT_BUFFER_ADDRESS, y
    89  c988 e63b                       inc TILE_OFFSET
    90  c98a 20d9c9                     jsr checkTileOffset
    91                          
    92                          
    93                          .endOut:
    94                                  ; just render this row
    95  c98d a53b                       lda TILE_OFFSET
    96  c98f 4a                         lsr
    97  c990 4a                         lsr
    98  c991 4a                         lsr
    99  c992 4a                         lsr
   100                          
   101  c993 a8                         tay
   102  c994 20ecf0                     jsr tilemapRenderRowToLcd
   103  c997 a638                       ldx SAVE_X
   104  c999 a439                       ldy SAVE_Y
   105  c99b a53a                       lda SAVE_A
   106  c99d 58                         cli
   107  c99e 60                         rts
   108                          
   109                          .bellOut
   110  c99f 2017fe                     jsr hbc56Bell
   111  c9a2 4c8dc9                     jmp .endOut
   112                          
   113                          .newline
   114  c9a5 a920                       lda #' '
   115  c9a7 a43b                       ldy TILE_OFFSET
   116  c9a9 99007a                     sta TILEMAP_DEFAULT_BUFFER_ADDRESS, y
   117                                  ; just render this row
   118  c9ac a53b                       lda TILE_OFFSET
   119  c9ae 4a                         lsr
   120  c9af 4a                         lsr
   121  c9b0 4a                         lsr
   122  c9b1 4a                         lsr
   123  c9b2 a8                         tay
   124  c9b3 2013f1                     jsr tilemapRenderToLcd
   125                          
   126  c9b6 a53b                       lda TILE_OFFSET
   127  c9b8 18                         clc
   128  c9b9 6910                       adc #16
   129  c9bb 29f0                       and #$F0
   130  c9bd 853b                       sta TILE_OFFSET
   131  c9bf 20d9c9                     jsr checkTileOffset
   132  c9c2 4c8dc9                     jmp .endOut
   133                          
   134                          .backspace
   135  c9c5 a920                       lda #' '
   136  c9c7 a43b                       ldy TILE_OFFSET
   137  c9c9 99007a                     sta TILEMAP_DEFAULT_BUFFER_ADDRESS, y
   138  c9cc c63b                       dec TILE_OFFSET
   139  c9ce a43b                       ldy TILE_OFFSET
   140  c9d0 a920                       lda #' '
   141  c9d2 99007a                     sta TILEMAP_DEFAULT_BUFFER_ADDRESS, y
   142  c9d5 4c8dc9                     jmp .endOut
   143  c9d8 60                 	rts
   144                          
   145                          checkTileOffset:
   146                          
   147  c9d9 a53b                       lda TILE_OFFSET
   148  c9db c980                       cmp #128
   149  c9dd 9023                       bcc .offsetOk
   150                          
   151                                  ; scroll
   152  c9df a200                       ldx #0
   153  c9e1 a010                       ldy #16
   154                          -
   155  c9e3 b9007a                     lda TILEMAP_DEFAULT_BUFFER_ADDRESS, y
   156  c9e6 9d007a                     sta TILEMAP_DEFAULT_BUFFER_ADDRESS, x
   157  c9e9 e8                         inx
   158  c9ea c8                         iny
   159  c9eb c080                       cpy #128
   160  c9ed d0f4                       bne -
   161  c9ef a970                       lda #128-16
   162  c9f1 853b                       sta TILE_OFFSET
   163                          
   164                                  ; clear the last row
   165  c9f3 a210a920ca9d707a...        +memset TILEMAP_DEFAULT_BUFFER_ADDRESS + 128 - 16, ' ', 16
   166                          
   167  c9ff 2013f1                     jsr tilemapRenderToLcd
   168                          
   169                          .offsetOk

; ******** Source: basic_glcd.asm
    14  ca02 60                             ; output routines
    15                          
    16                          
    17                          ; -----------------------------------------------------------------------------
    18                          ; metadata for the HBC-56 kernel
    19                          ; -----------------------------------------------------------------------------
    20                          hbc56Meta:
    21  ca03 4c16ca4241534943...        +setHbcMetaTitle "BASIC (GFX LCD)"
    22  ca28 adcd7c09208dcd7c           +consoleLCDMode

; ******** Source: kernel.asm
     1                          ; 6502 - HBC-56 Kernel
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          ;
    10                          
    11                          HBC56_INT_VECTOR = $7e00
    12                          HBC56_NMI_VECTOR = $7e04
    13                          HBC56_RST_VECTOR = kernelMain
    14                          
    15                          HBC56_KERNEL_START = $e000
    16                          HBC56_META_VECTOR  = HBC56_KERNEL_START-4
    17                          
    18                          RTI_OPCODE = $40
    19                          JMP_OPCODE = $4c
    20                          
    21                          ; -------------------------
    22                          ; I/O devices
    23                          ; -------------------------
    24                          LCD_IO_PORT             = $02
    25                          TMS9918_IO_PORT         = $10
    26                          UART_IO_PORT            = $20
    27                          AY_IO_PORT              = $40
    28                          KB_IO_PORT              = $80
    29                          NES_IO_PORT             = $82
    30                          INT_IO_PORT             = $df
    31                          VIA_IO_PORT             = $f0
    32                          ROM_BANK_REG            = $08
    33                          
    34                          ; -------------------------
    35                          ; Kernel Zero Page
    36                          ; -------------------------
    37                          HBC56_KERNEL_ZP_START   = $18
    38                          
    39                          TILEMAP_ZP_START        = HBC56_KERNEL_ZP_START
    40                          TILEMAP_ZP_END          = TILEMAP_ZP_START + 6
    41                          
    42                          BITMAP_ZP_START         = TILEMAP_ZP_END
    43                          BITMAP_ZP_END           = BITMAP_ZP_START + 6
    44                          
    45                          !ifdef HBC56_DISABLE_TMS9918 { .TMS_ZP_SIZE = 0 } else { .TMS_ZP_SIZE = 4 }
    46                          TMS9918_ZP_START        = BITMAP_ZP_END
    47                          TMS9918_ZP_END          = TMS9918_ZP_START + .TMS_ZP_SIZE
    48                          
    49                          !ifdef HBC56_DISABLE_LCD { .LCD_ZP_SIZE = 0 } else { .LCD_ZP_SIZE = 2 }
    50                          LCD_ZP_START            = TMS9918_ZP_END
    51                          LCD_ZP_END              = LCD_ZP_START + .LCD_ZP_SIZE
    52                          
    53                          !ifdef HBC56_DISABLE_UART { .UART_ZP_SIZE = 0 } else { .UART_ZP_SIZE = 4 }
    54                          UART_ZP_START            = LCD_ZP_END
    55                          UART_ZP_END              = UART_ZP_START + .UART_ZP_SIZE
    56                          
    57                          MEMORY_ZP_START         = UART_ZP_END
    58                          MEMORY_ZP_END           = MEMORY_ZP_START + 6
    59                          
    60                          STR_ADDR                = MEMORY_ZP_END
    61                          STR_ADDR_L              = MEMORY_ZP_END
    62                          STR_ADDR_H              = MEMORY_ZP_END + 1
    63                          
    64                          DELAY_L                 = STR_ADDR_H + 1
    65                          DELAY_H                 = DELAY_L + 1
    66                          
    67                          HBC56_KERNEL_ZP_END     = DELAY_H + 1
    68                          HBC56_USER_ZP_START     = HBC56_KERNEL_ZP_END
    69                          
    70                          ;!warn "Total ZP used: ",STR_ADDR_H-HBC56_KERNEL_ZP_START
    71                          
    72                          
    73                          !ifndef HAVE_TMS9918 { HBC56_DISABLE_SFXMAN=1 }
    74                          
    75                          ; -------------------------
    76                          ; Kernel RAM
    77                          ; -------------------------
    78                          HBC56_KERNEL_RAM_START  = $7a00
    79                          
    80                          TILEMAP_RAM_START       = HBC56_KERNEL_RAM_START
    81                          TILEMAP_RAM_END         = TILEMAP_RAM_START + $116
    82                          
    83                          BITMAP_RAM_START        = TILEMAP_RAM_END
    84                          BITMAP_RAM_END          = BITMAP_RAM_START + 16
    85                          
    86                          !ifdef HBC56_DISABLE_TMS9918 { .TMS_RAM_SIZE = 0 } else { .TMS_RAM_SIZE = 50 }
    87                          TMS9918_RAM_START       = BITMAP_RAM_END
    88                          TMS9918_RAM_END         = TMS9918_RAM_START + .TMS_RAM_SIZE
    89                          
    90                          !ifdef HBC56_DISABLE_LCD { .LCD_RAM_SIZE = 0 } else { .LCD_RAM_SIZE = 42 }
    91                          LCD_RAM_START           = TMS9918_RAM_END
    92                          LCD_RAM_END             = LCD_RAM_START + .LCD_RAM_SIZE
    93                          
    94                          !ifdef HBC56_DISABLE_UART { .UART_RAM_SIZE = 0 } else { .UART_RAM_SIZE = 256 }
    95                          UART_RAM_START            = LCD_RAM_END
    96                          UART_RAM_END              = UART_RAM_START + .UART_RAM_SIZE
    97                          
    98                          VIA_RAM_START             = UART_RAM_END
    99                          VIA_RAM_END               = VIA_RAM_START + 1
   100                          
   101                          !ifdef HBC56_DISABLE_SFXMAN { .SFXMAN_RAM_SIZE = 0 } else { .SFXMAN_RAM_SIZE = 18 }
   102                          SFXMAN_RAM_START        = VIA_RAM_END
   103                          SFXMAN_RAM_END          = SFXMAN_RAM_START + .SFXMAN_RAM_SIZE
   104                          
   105                          BCD_RAM_START           = SFXMAN_RAM_END
   106                          BCD_RAM_END             = BCD_RAM_START + 3
   107                          
   108                          KB_RAM_START            = BCD_RAM_END
   109                          KB_RAM_END              = KB_RAM_START + 64
   110                          
   111                          NES_RAM_START            = KB_RAM_END
   112                          NES_RAM_END              = NES_RAM_START + 3
   113                          
   114                          LAST_MODULE_RAM_END     = NES_RAM_END
   115                          
   116                          HBC56_TICKS             = LAST_MODULE_RAM_END
   117                          HBC56_SECONDS_L         = LAST_MODULE_RAM_END + 1
   118                          HBC56_SECONDS_H         = LAST_MODULE_RAM_END + 2
   119                          HBC56_TMP               = LAST_MODULE_RAM_END + 3
   120                          
   121                          HBC56_CONSOLE_FLAGS     = LAST_MODULE_RAM_END + 4
   122                          HBC56_CONSOLE_FLAG_CURSOR = $80
   123                          HBC56_CONSOLE_FLAG_NES    = $40
   124                          HBC56_CONSOLE_FLAG_LCD    = $20
   125                          HBC56_CONSOLE_FLAG_NOWAIT = $10
   126                          
   127                          HBC56_TMP_X             = LAST_MODULE_RAM_END + 5
   128                          HBC56_TMP_Y             = LAST_MODULE_RAM_END + 6
   129                          
   130                          HBC56_META_TITLE_MAX_LEN = 16
   131                          HBC56_META_TITLE        = LAST_MODULE_RAM_END + 7
   132                          HBC56_META_TITLE_END    = HBC56_META_TITLE + HBC56_META_TITLE_MAX_LEN + 1
   133                          HBC56_META_TITLE_LEN    = HBC56_META_TITLE_END + 1
   134                          
   135                          ; callback function on vsync
   136                          HBC56_VSYNC_CALLBACK = HBC56_META_TITLE_LEN + 1
   137                          HBC56_VIA_CALLBACK   = HBC56_VSYNC_CALLBACK + 2
   138                          
   139                          
   140                          HBC56_KERNEL_RAM_END    = HBC56_VIA_CALLBACK + 2
   141                          HBC56_KERNEL_RAM_SIZE   = HBC56_KERNEL_RAM_END - HBC56_KERNEL_RAM_START
   142                          ;!warn "Total RAM used: ",HBC56_KERNEL_RAM_SIZE
   143                          

; ******** Source: ../lib\hbc56.asm
     1                          ; 6502 - HBC-56
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          ;
    10                          
    11                          !cpu w65c02
    12                          !initmem $FF
    13                          cputype = $65c02
    14                          

; ******** Source: ../lib\hbc56.inc
     1                          ; 6502 - HBC-56
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          ;
    10                          
    11                          ; Base address of the 256 IO port memory range
    12                          IO_PORT_BASE_ADDRESS    = $7f00
    13                          
    14                          
    15                          ; -------------------------
    16                          ; ASCII constants
    17                          ; -------------------------
    18                          ASCII_RETURN    = $0A
    19                          ASCII_CR        = $0D
    20                          ASCII_BACKSPACE = $08
    21                          ASCII_BELL      = $07

; ******** Source: ../lib\hbc56.asm
    16                          
    17                          DEFAULT_HBC56_NMI_VECTOR = $FFE0
    18                          DEFAULT_HBC56_RST_VECTOR = $8000
    19                          DEFAULT_HBC56_INT_VECTOR = $FFE0
    20                          
    21                          !macro hbc56Title .title {
    22                          HBC56_TITLE_TEXT:
    23                                  !text .title
    24                          HBC56_TITLE_TEXT_LEN = * - HBC56_TITLE_TEXT
    25                                  !byte 0 ; nul terminator for game name
    26                          }
    27                          
    28                          *=DEFAULT_HBC56_INT_VECTOR
    29  ffe0 40                         rti
    30                          
    31                          hbc56Delay:
    32  ffe1 a000                       ldy #0
    33                          hbc56CustomDelay:
    34  ffe3 a200                       ldx #0
    35                          -
    36  ffe5 ca                         dex
    37  ffe6 d0fd                       bne -
    38  ffe8 a200                       ldx #0
    39  ffea 88                         dey
    40  ffeb d0f8                       bne -
    41  ffed 60                         rts
    42                          
    43                          *=$FFFA
    44  fffa 047e               !ifdef HBC56_NMI_VECTOR { !word HBC56_NMI_VECTOR } else { !word DEFAULT_HBC56_NMI_VECTOR }
    45  fffc b1fc               !ifdef HBC56_RST_VECTOR { !word HBC56_RST_VECTOR } else { !word DEFAULT_HBC56_RST_VECTOR }
    46  fffe 007e               !ifdef HBC56_INT_VECTOR { !word HBC56_INT_VECTOR } else { !word DEFAULT_HBC56_INT_VECTOR }
    47                          
    48                          
    49                          *=DEFAULT_HBC56_RST_VECTOR

; ******** Source: kernel.asm
   144                          
   145                          *=HBC56_KERNEL_START
   146                          

; ******** Source: ../lib\ut\ascii.asm
     1                          ; 6502 - ASCII subroutines
     2                          ;
     3                          ; Copyright (c) 2022 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          ;
    10                          
    11                          ; -----------------------------------------------------------------------------
    12                          ; isLower: Is the ASCII character a lower-case letter (a-z)
    13                          ; -----------------------------------------------------------------------------
    14                          ; Inputs:
    15                          ;   A: ASCII character
    16                          ; Outputs:
    17                          ;   Carry set if lower case, carry clear if not lower case
    18                          ; -----------------------------------------------------------------------------
    19                          isLower:
    20  e000 c961                       cmp #'a'
    21  e002 9005                       bcc @notLower   ; less than 'a'?
    22  e004 c97b                       cmp #'z' + 1
    23  e006 9002                       bcc @isLower    ; less than or equal 'z'?
    24  e008 18                         clc
    25                          @notLower:
    26  e009 60                         rts
    27                          
    28                          @isLower
    29  e00a 38                         sec
    30  e00b 60                         rts
    31                          
    32                          
    33                          ; -----------------------------------------------------------------------------
    34                          ; isUpper: Is the ASCII character a upper-case letter (A-Z)
    35                          ; -----------------------------------------------------------------------------
    36                          ; Inputs:
    37                          ;   A: ASCII character
    38                          ; Outputs:
    39                          ;   Carry set if upper case, carry clear if not upper case
    40                          ; -----------------------------------------------------------------------------
    41                          isUpper:
    42  e00c c941                       cmp #'A'
    43  e00e 9005                       bcc @notUpper   ; less than 'A'?
    44  e010 c95b                       cmp #'Z' + 1
    45  e012 9002                       bcc @isUpper    ; less than or equal 'Z'?
    46  e014 18                         clc
    47                          @notUpper:
    48  e015 60                         rts
    49                          
    50                          @isUpper
    51  e016 38                         sec
    52  e017 60                         rts
    53                          
    54                          ; -----------------------------------------------------------------------------
    55                          ; isAlpha: Is the ASCII character alphanumeric (A-Z, a-z)
    56                          ; -----------------------------------------------------------------------------
    57                          ; Inputs:
    58                          ;   A: ASCII character
    59                          ; Outputs:
    60                          ;   Carry set if alpha, carry clear if not alpha
    61                          ; -----------------------------------------------------------------------------
    62                          isAlpha:
    63  e018 2000e0                     jsr isLower
    64  e01b 90ef                       bcc isUpper
    65  e01d 60                         rts
    66                          
    67                          
    68                          ; -----------------------------------------------------------------------------
    69                          ; isDigit: Is the ASCII character a decimal digit (0-9)
    70                          ; -----------------------------------------------------------------------------
    71                          ; Inputs:
    72                          ;   A: ASCII character
    73                          ; Outputs:
    74                          ;   Carry set if digit, carry clear if not digit
    75                          ; -----------------------------------------------------------------------------
    76                          isDigit:
    77  e01e c930                       cmp #'0'
    78  e020 9005                       bcc @notDigit    ; less than '0'?
    79  e022 c93a                       cmp #'9' + 1
    80  e024 9002                       bcc @isDigit     ; less than or equal '9'?
    81  e026 18                         clc
    82                          
    83                          @notDigit:
    84  e027 60                         rts
    85                          
    86                          @isDigit
    87  e028 38                         sec
    88  e029 60                         rts
    89                          
    90                          
    91                          ; -----------------------------------------------------------------------------
    92                          ; isAlNum: Is the ASCII character alphanumeric (A-Z, a-z, 0-9)
    93                          ; -----------------------------------------------------------------------------
    94                          ; Inputs:
    95                          ;   A: ASCII character
    96                          ; Outputs:
    97                          ;   Carry set if alphanumeric, carry clear if not alphanumeric
    98                          ; -----------------------------------------------------------------------------
    99                          isAlNum:
   100  e02a 2018e0                     jsr isAlpha
   101  e02d 90ef                       bcc isDigit
   102  e02f 60                         rts
   103                          
   104                          ; -----------------------------------------------------------------------------
   105                          ; isDigitX: Is the ASCII character a hex digit (A-F, a-f, 0-9)
   106                          ; -----------------------------------------------------------------------------
   107                          ; Inputs:
   108                          ;   A: ASCII character
   109                          ; Outputs:
   110                          ;   Carry set if hexadecimal, carry clear if not hexadecimal
   111                          ; -----------------------------------------------------------------------------
   112                          isDigitX:
   113  e030 201ee0                     jsr isDigit
   114  e033 b013                       bcs @endIsDigitX
   115  e035 c941                       cmp #'A'
   116  e037 900d                       bcc @notHexDigit   ; less than 'A'?
   117  e039 c947                       cmp #'F' + 1
   118  e03b 900a                       bcc @isHexDigit    ; less than or equal 'F'?
   119  e03d c961                       cmp #'a'
   120  e03f 9005                       bcc @notHexDigit   ; less than 'a'?
   121  e041 c967                       cmp #'f' + 1
   122  e043 9002                       bcc @isHexDigit    ; less than or equal 'f'?
   123  e045 18                         clc
   124                          @notHexDigit:
   125  e046 60                         rts
   126                          
   127                          @isHexDigit
   128  e047 38                         sec
   129                          
   130                          @endIsDigitX
   131  e048 60                         rts
   132                          
   133                          
   134                          ; -----------------------------------------------------------------------------
   135                          ; isSpace: Is the ASCII character a whitespace character?
   136                          ; -----------------------------------------------------------------------------
   137                          ; Inputs:
   138                          ;   A: ASCII character
   139                          ; Outputs:
   140                          ;   Carry set if space, carry clear if not space
   141                          ; -----------------------------------------------------------------------------
   142                          isSpace:
   143  e049 c920                       cmp #' '
   144  e04b f01c                       beq @isSpace
   145  e04d b018                       bcs @notSpace
   146  e04f c90a                       cmp #'\n'
   147  e051 f016                       beq @isSpace
   148  e053 c90d                       cmp #'\r'
   149  e055 f012                       beq @isSpace
   150  e057 c909                       cmp #'\t'
   151  e059 f00e                       beq @isSpace
   152  e05b c90d                       cmp #'\r'
   153  e05d f00a                       beq @isSpace
   154  e05f c90b                       cmp #$0b
   155  e061 f006                       beq @isSpace
   156  e063 c90c                       cmp #$0c
   157  e065 f002                       beq @isSpace
   158                          
   159                          @notSpace:
   160  e067 18                         clc
   161  e068 60                         rts
   162                          
   163                          @isSpace
   164  e069 38                         sec
   165  e06a 60                         rts
   166                          
   167                          ; -----------------------------------------------------------------------------
   168                          ; toUpper: convert an ascii character to upper case
   169                          ; -----------------------------------------------------------------------------
   170                          ; Inputs:
   171                          ;   A: ascii character
   172                          ; Outputs:
   173                          ;   A: upper case ascii character
   174                          ;   C: set if character was converted
   175                          ; -----------------------------------------------------------------------------
   176                          toUpper:
   177  e06b 2000e0                     jsr isLower
   178  e06e 9002                       bcc @endToUpper
   179  e070 4920                       eor #$20        ; convert (subtract $20)
   180                          
   181                          @endToUpper
   182  e072 60                         rts        
   183                          
   184                          ; -----------------------------------------------------------------------------
   185                          ; toLower: convert an ascii character to lower case
   186                          ; -----------------------------------------------------------------------------
   187                          ; Inputs:
   188                          ;   A: ascii character
   189                          ; Outputs:
   190                          ;   A: lower case ascii character
   191                          ;   C: set if character was converted
   192                          ; -----------------------------------------------------------------------------
   193                          toLower:
   194  e073 200ce0                     jsr isUpper
   195  e076 9002                       bcc @endToUpper
   196                          
   197  e078 0920                       ora #$20        ; convert (add $20)
   198                          
   199                          @endToUpper

; ******** Source: kernel.asm
   147  e07a 60                 

; ******** Source: ../lib\ut\bcd.asm
     1                          ; 6502 - BCD subroutines
     2                          ;
     3                          ; Copyright (c) 2020 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          ;
    10                          
    11                          
    12                          !ifndef BCD_RAM_START { BCD_RAM_START = $7810
    13                                  !warn "BCD_RAM_START not provided. Defaulting to ", BCD_RAM_START
    14                          }
    15                          
    16                          ; -------------------------
    17                          ; High RAM
    18                          ; -------------------------
    19                          BCD_TMP1        = BCD_RAM_START
    20                          BCD_TMP2        = BCD_RAM_START + 1
    21                          BCD_TMP3        = BCD_RAM_START + 2
    22                          .BCD_RAM_SIZE   = 3
    23                          
    24                          !if BCD_RAM_END < (BCD_RAM_START + .BCD_RAM_SIZE) {
    25                                  !error "BCD_RAM requires ",BCD_RAM_SIZE," bytes. Allocated ",BCD_RAM_END - BCD_RAM_START
    26                          }
    27                          
    28                          
    29                          ; -----------------------------------------------------------------------------
    30                          ; bin2bcd8: convert an unsigned byte to a 2-digit bcd value
    31                          ; -----------------------------------------------------------------------------
    32                          ; Inputs:
    33                          ;   A: value
    34                          ; Outputs:
    35                          ;   BCD value in R8
    36                          ; -----------------------------------------------------------------------------
    37                          bin2bcd8:
    38  e07b 8d837c               sta BCD_TMP1
    39  e07e a900                 lda #0
    40  e080 8d847c               sta BCD_TMP2
    41  e083 8d857c               sta BCD_TMP3
    42  e086 a208                 ldx #8 
    43  e088 f8                   sed    
    44                          .loop:
    45  e089 0e837c               asl BCD_TMP1
    46  e08c ad847c               lda BCD_TMP2
    47  e08f 6d847c               adc BCD_TMP2
    48  e092 8d847c               sta BCD_TMP2
    49  e095 ad857c               lda BCD_TMP3
    50  e098 6d857c               adc BCD_TMP3
    51  e09b 8d857c               sta BCD_TMP3
    52  e09e ca                   dex
    53  e09f d0e8                 bne .loop
    54  e0a1 d8                   cld   
    55  e0a2 60                   rts
    56                          

; ******** Source: kernel.asm
   148                          

; ******** Source: ../lib\ut\memory.asm
     1                          ; 6502
     2                          ;
     3                          ; Memory subroutines and macros
     4                          ;
     5                          ; Copyright (c) 2020 Troy Schrapel
     6                          ;
     7                          ; This code is licensed under the MIT license
     8                          ;
     9                          ; https://github.com/visrealm/hbc-56
    10                          ;
    11                          ;
    12                          

; ******** Source: ../lib\ut\memory.inc
     1                          ; 6502
     2                          ;
     3                          ; Memory subroutines and macros
     4                          ;
     5                          ; Copyright (c) 2020 Troy Schrapel
     6                          ;
     7                          ; This code is licensed under the MIT license
     8                          ;
     9                          ; https://github.com/visrealm/hbc-56
    10                          ;
    11                          ;
    12                          
    13                          ; -----------------------------------------------------------------------------
    14                          ; store16: Write a 16-bit immediate value to memory
    15                          ; -----------------------------------------------------------------------------
    16                          ; Inputs:
    17                          ;       .dst: destination address
    18                          ;       .val16: 16-bit value
    19                          ; -----------------------------------------------------------------------------
    20                          !macro store16 .dst, .val16 {
    21                                  lda #<.val16
    22                                  sta .addr
    23                                  lda #>.val16
    24                                  sta .addr + 1
    25                          }
    26                          
    27                          ; -----------------------------------------------------------------------------
    28                          ; memcpy: Copy a fixed number of bytes from .src to dest
    29                          ; -----------------------------------------------------------------------------
    30                          ; Inputs:
    31                          ;       .src: source address
    32                          ;       .dst: destination address
    33                          ;       .cnt: number of bytes
    34                          ; -----------------------------------------------------------------------------
    35                          !macro memcpy .dst, .src, .cnt {
    36                          !if .cnt <= 0 {
    37                                  !error "memcpy: invalid count: ", .cnt
    38                          } else if .cnt <= 8 {
    39                                  !for i, 0, .cnt - 1 {
    40                                          lda .src + i
    41                                          sta .dst + i
    42                                  }
    43                          } else { !if .cnt <= 256 {
    44                                  ldx #0
    45                          -
    46                                  lda .src, x
    47                                  sta .dst, x
    48                                  inx
    49                                  cpx #(.cnt & $ff)       
    50                                  bne -
    51                          } else {
    52                                  lda #<.src
    53                                  sta MEM_SRC
    54                                  lda #>.src
    55                                  sta MEM_SRC + 1
    56                          
    57                                  lda #<.dst
    58                                  sta MEM_DST
    59                                  lda #>.dst
    60                                  sta MEM_DST + 1
    61                          
    62                          
    63                                          lda #<.cnt
    64                                          sta MEM_LEN
    65                                          lda #>.cnt
    66                                          sta MEM_LEN + 1
    67                                          jsr memcpyMultiPage
    68                                  }
    69                          }
    70                          }
    71                          
    72                          !macro setMemCpySrc .src {
    73                                  lda #<.src
    74                                  sta MEM_SRC
    75                                  lda #>.src
    76                                  sta MEM_SRC + 1
    77                          }
    78                          
    79                          !macro setMemCpyDst .dst {
    80                                  lda #<.dst
    81                                  sta MEM_DST
    82                                  lda #>.dst
    83                                  sta MEM_DST + 1
    84                          }
    85                          
    86                          !macro setMemCpySrcInd .srcRef {
    87                                  lda .srcRef
    88                                  sta MEM_SRC
    89                                  lda .srcRef + 1
    90                                  sta MEM_SRC + 1
    91                          }
    92                          
    93                          !macro setMemCpyDstInd .dstRef {
    94                                  lda .dstRef
    95                                  sta MEM_DST
    96                                  lda .dstRef + 1
    97                                  sta MEM_DST + 1
    98                          }
    99                          
   100                          !macro memcpySinglePage .bytes {
   101                          
   102                                  !if .bytes <= 0 {
   103                                          !error "memcpySinglePage: invalid count: ", .bytes
   104                                  }       
   105                          
   106                                  ldy #.bytes
   107                                  jsr memcpySinglePage
   108                          }
   109                          
   110                          
   111                          ; -----------------------------------------------------------------------------
   112                          ; memcpyPort: Copy a fixed number of bytes from .src ram to dest port
   113                          ; -----------------------------------------------------------------------------
   114                          ; Inputs:
   115                          ;       .src: source address
   116                          ;       .dst: destination address
   117                          ;       .cnt: number of bytes
   118                          ; -----------------------------------------------------------------------------
   119                          !macro memcpyPort .dst, .src, .cnt {
   120                                  !if .cnt <= 0 {
   121                                          !error "memcpyPort: invalid count: ", .cnt
   122                                  }
   123                                  
   124                                  lda #<.src
   125                                  sta MEM_SRC
   126                                  lda #>.src
   127                                  sta MEM_SRC + 1
   128                          
   129                                  lda #<.dst
   130                                  sta MEM_DST
   131                                  lda #>.dst
   132                                  sta MEM_DST + 1
   133                          
   134                                  !if .cnt <= 256 {
   135                                          ldy #<.cnt                                      
   136                                          jsr memcpySinglePagePort
   137                                  } else {
   138                                          lda #<.cnt
   139                                          sta MEM_LEN
   140                                          lda #>.cnt
   141                                          sta MEM_LEN + 1
   142                                          jsr memcpyMultiPagePort
   143                                  }
   144                          }
   145                          
   146                          !zone {
   147                          
   148                          ; -----------------------------------------------------------------------------
   149                          ; memset: Set a fixed number of bytes to a single value
   150                          ; -----------------------------------------------------------------------------
   151                          ; Inputs:
   152                          ;       .dst: destination address
   153                          ;       val: the byte value
   154                          ;       .cnt: number of bytes
   155                          ; -----------------------------------------------------------------------------
   156                          !macro memset .dst, .val, .cnt {
   157                          !if .cnt <= 0 {
   158                                  !error "memset: invalid count: ", .cnt
   159                          } else if .cnt <= 8 {
   160                                  lda #.val
   161                                  !for i, 0, .cnt - 1 {
   162                                  sta .dst + i
   163                                  }
   164                          } else if .cnt <= 256 {
   165                                  ldx #<.cnt
   166                                  lda #.val
   167                          -
   168                                  dex
   169                                  sta .dst, x
   170                                  cpx #0
   171                                  bne -
   172                          } else {
   173                                  lda #<.dst
   174                                  sta MEM_DST
   175                                  lda #>.dst
   176                                  sta MEM_DST + 1
   177                                  lda #<.cnt
   178                                  sta MEM_LEN
   179                                  lda #>.cnt
   180                                  sta MEM_LEN + 1
   181                                  lda #.val
   182                                  jsr memsetMultiPage
   183                          }
   184                          }
   185                          
   186                          

; ******** Source: ../lib\ut\memory.asm
    14                          
    15                          
    16                          !ifndef MEMORY_ZP_START { MEMORY_ZP_START = $48
    17                                  !warn "MEMORY_ZP_START not provided. Defaulting to ", MEMORY_ZP_START
    18                          }
    19                          
    20                          ; -------------------------
    21                          ; Zero page
    22                          ; -------------------------
    23                          MEM_DST = MEMORY_ZP_START
    24                          MEM_SRC = MEMORY_ZP_START + 2
    25                          MEM_LEN = MEMORY_ZP_START + 4
    26                          MEMORY_ZP_SIZE  = 6
    27                          
    28                          
    29                          !if MEMORY_ZP_END < (MEMORY_ZP_START + MEMORY_ZP_SIZE) {
    30                                  !error "MEMORY_ZP requires ",MEMORY_ZP_SIZE," bytes. Allocated ",MEMORY_ZP_END - MEMORY_ZP_START
    31                          }
    32                          
    33                          ; -----------------------------------------------------------------------------
    34                          ; memcpySinglePage: Copy up to 255 bytes 
    35                          ; -----------------------------------------------------------------------------
    36                          ; Inputs:
    37                          ;       MEM_SRC: src address
    38                          ;       MEM_DST: dst address
    39                          ;       Y:      bytes
    40                          ; -----------------------------------------------------------------------------
    41                          memcpySinglePage:
    42  e0a3 c000                       cpy #0
    43  e0a5 f009                       beq .endMemcpySinglePage
    44                          -
    45  e0a7 88                         dey
    46  e0a8 b130                       lda (MEM_SRC), Y
    47  e0aa 912e                       sta (MEM_DST), Y
    48  e0ac c000                       cpy #0
    49  e0ae d0f7                       bne -
    50                          .endMemcpySinglePage:
    51  e0b0 60                         rts
    52                          ; -----------------------------------------------------------------------------
    53                          
    54                          
    55                          
    56                          ; -----------------------------------------------------------------------------
    57                          ; memcpySinglePagePort: Copy up to 255 bytes 
    58                          ; -----------------------------------------------------------------------------
    59                          ; Inputs:
    60                          ;       MEM_SRC: src address
    61                          ;       MEM_DST: dst address (port)
    62                          ;       Y:      bytes
    63                          ; -----------------------------------------------------------------------------
    64                          memcpySinglePagePort:
    65  e0b1 c000                       cpy #0
    66  e0b3 f009                       beq .endMemcpySinglePagePort
    67                          -
    68  e0b5 88                         dey
    69  e0b6 b130                       lda (MEM_SRC), Y
    70  e0b8 852e                       sta MEM_DST
    71  e0ba c000                       cpy #0
    72  e0bc d0f7                       bne -
    73                          .endMemcpySinglePagePort
    74  e0be 60                         rts
    75                          ; -----------------------------------------------------------------------------
    76                          
    77                          
    78                          
    79                          ; -----------------------------------------------------------------------------
    80                          ; memcpyMultiPage: Copy an up to 2^15 bytes 
    81                          ; -----------------------------------------------------------------------------
    82                          ; Inputs:
    83                          ;       MEM_SRC: src address
    84                          ;       MEM_DST: dst address
    85                          ;       MEM_LEN: length
    86                          ; -----------------------------------------------------------------------------
    87                          memcpyMultiPage:
    88                          
    89                          !ifdef ALLOW_SELF_MODIFYING_CODE {
    90                                  lda MEM_SRC
    91                                  sta .loadIns + 1
    92                                  lda MEM_SRC + 1
    93                                  sta .loadIns + 2
    94                          
    95                                  lda MEM_DST
    96                                  sta .storeIns + 1
    97                                  lda MEM_DST + 1
    98                                  sta .storeIns + 2
    99                          
   100                          .loadIns:
   101                                  lda SELF_MODIFY_ADDR, Y
   102                                  
   103                          .storeIns:
   104                                  sta SELF_MODIFY_ADDR, Y
   105                                  dey
   106                                  bne .loadIns
   107                                  inc .loadIns + 2
   108                                  inc .storeIns + 2
   109                                  dex
   110                                  bne .loadIns
   111                          } else {
   112  e0bf a000                       ldy #0
   113  e0c1 a633                       ldx MEM_LEN + 1
   114                          - 
   115  e0c3 b130                       lda (MEM_SRC),y ; could unroll to any power of 2
   116  e0c5 912e                       sta (MEM_DST),y
   117  e0c7 c8                         iny
   118  e0c8 d0f9                       bne -
   119  e0ca ca                         dex
   120  e0cb f007                       beq .memcpyMultiPageRemaining
   121  e0cd e631                       inc MEM_SRC + 1
   122  e0cf e62f                       inc MEM_DST + 1
   123  e0d1 4cc3e0                     jmp -
   124                          .memcpyMultiPageRemaining ; remaining bytes
   125  e0d4 a632                       ldx MEM_LEN
   126  e0d6 f008                       beq .memcpyMultiPageEnd
   127                          - ; X bytes
   128  e0d8 b130                       lda (MEM_SRC),y
   129  e0da 912e                       sta (MEM_DST),y
   130  e0dc c8                         iny
   131  e0dd ca                         dex
   132  e0de d0f8                       bne -
   133                          .memcpyMultiPageEnd
   134                          }
   135                          
   136  e0e0 60                         rts
   137                          ; -----------------------------------------------------------------------------
   138                          
   139                          
   140                          ; -----------------------------------------------------------------------------
   141                          ; memcpyMultiPagePort: Copy an up to 2^15 bytes 
   142                          ; -----------------------------------------------------------------------------
   143                          ; Inputs:
   144                          ;       MEM_SRC: src address
   145                          ;       MEM_DST: dst address (port)
   146                          ;       MEM_LEN: length
   147                          ; -----------------------------------------------------------------------------
   148                          memcpyMultiPagePort:
   149                          
   150  e0e1 a000                       ldy #0
   151  e0e3 a633                       ldx MEM_LEN + 1
   152                          - 
   153  e0e5 b130                       lda (MEM_SRC),y ; could unroll to any power of 2
   154  e0e7 852e                       sta MEM_DST
   155  e0e9 c8                         iny
   156  e0ea d0f9                       bne -
   157  e0ec ca                         dex
   158  e0ed f005                       beq .memcpyMultiPagePortRemaining
   159  e0ef e631                       inc MEM_SRC + 1
   160  e0f1 4ce5e0                     jmp -
   161                          .memcpyMultiPagePortRemaining ; remaining bytes
   162  e0f4 a632                       ldx MEM_LEN
   163  e0f6 f008                       beq .memcpyMultiPagePortEnd
   164                          - ; X bytes
   165  e0f8 b130                       lda (MEM_SRC),y
   166  e0fa 852e                       sta MEM_DST
   167  e0fc c8                         iny
   168  e0fd ca                         dex
   169  e0fe d0f8                       bne -
   170                          .memcpyMultiPagePortEnd
   171  e100 60                         rts
   172                          ; -----------------------------------------------------------------------------
   173                          
   174                          
   175                          ; -----------------------------------------------------------------------------
   176                          ; memsetSinglePage: set a block of memory data
   177                          ; -----------------------------------------------------------------------------
   178                          ; Inputs:
   179                          ;        A:     value to set
   180                          ;        MEM_DST: start address
   181                          ;        Y:     bytes
   182                          ; -----------------------------------------------------------------------------
   183                          memsetSinglePage:
   184  e101 c000                       cpy #0
   185  e103 f007                       beq .doneCpy
   186                          -
   187  e105 88                         dey
   188  e106 912e                       sta (MEM_DST), y
   189  e108 c000                       cpy #0
   190  e10a d0f9                       bne -
   191                          .doneCpy
   192  e10c 60                         rts
   193                          
   194                          
   195                          ; -----------------------------------------------------------------------------
   196                          ; memsetMultiPage: set a block of memory data
   197                          ; -----------------------------------------------------------------------------
   198                          ; Inputs:
   199                          ;        A: value
   200                          ;        MEM_DST: start address
   201                          ;        MEM_LEN: length
   202                          ; -----------------------------------------------------------------------------
   203                          memsetMultiPage:
   204  e10d a633                       ldx MEM_LEN + 1
   205  e10f d005                       bne .doneSet
   206  e111 a432                       ldy MEM_LEN
   207  e113 4c01e1                     jmp memsetSinglePage
   208                          .doneSet
   209  e116 a000                       ldy #0
   210                          - 
   211  e118 912e                       sta (MEM_DST),y ; could unroll to any power of 2
   212  e11a c8                         iny
   213  e11b d0fb                       bne -
   214  e11d ca                         dex
   215  e11e f005                       beq .doneSet2
   216  e120 e62f                       inc MEM_DST + 1
   217  e122 4c18e1                     jmp -
   218                          .doneSet2 ; remaining bytes
   219  e125 a632                       ldx MEM_LEN
   220  e127 f006                       beq .doneSet3
   221                          - ; X bytes
   222  e129 912e                       sta (MEM_DST),y
   223  e12b c8                         iny
   224  e12c ca                         dex
   225  e12d d0fa                       bne -
   226                          .doneSet3
   227  e12f 60                         rts

; ******** Source: kernel.asm
   149                          

; ******** Source: ../lib\ut\tables.asm
     1                          ; 6502 - Useful tables
     2                          ;
     3                          ; Copyright (c) 2022 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          ;
    10                          
    11                          tableBitFromLeft:
    12  e130 8040201008040201   !byte $80,$40,$20,$10,$08,$04,$02,$01
    13                          tableInvBitFromLeft:
    14  e138 7fbfdfeff7fbfdfe   !byte $7f,$bf,$df,$ef,$f7,$fb,$fd,$fe
    15                          tableBitFromRight:
    16  e140 0102040810204080   !byte $01,$02,$04,$08,$10,$20,$40,$80
    17                          tableInvBitFromRight:
    18  e148 fefdfbf7efdfbf7f   !byte $fe,$fd,$fb,$f7,$ef,$df,$bf,$7f
    19                          tableBitsFromLeft:
    20  e150 80c0e0f0f8fcfeff   !byte $80,$c0,$e0,$f0,$f8,$fc,$fe,$ff

; ******** Source: kernel.asm
   150                          
   151                          
   152                          !ifndef HBC56_DISABLE_AY3891X {

; ******** Source: ../lib\sfx\ay3891x.asm
     1                          ; 6502 - AY-3-819x PSG
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          

; ******** Source: ../lib\sfx\ay3891x.inc
     1                          ; 6502 - AY-3-819x PSG
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          
    10                          
    11                          
    12                          !macro ayWrite .dev, .reg, .val {
    13                                  lda #.reg
    14                                  sta IO_PORT_BASE_ADDRESS | AY_IO_PORT | AY_ADDR | .dev
    15                                  lda #.val
    16                                  sta IO_PORT_BASE_ADDRESS | AY_IO_PORT | AY_WRITE | .dev
    17                          }        
    18                          
    19                          !macro ayRead .dev, .reg {
    20                                  lda #.reg
    21                                  sta IO_PORT_BASE_ADDRESS | AY_IO_PORT | AY_ADDR | .dev
    22                                  lda IO_PORT_BASE_ADDRESS | AY_IO_PORT | AY_READ | .dev
    23                          }        
    24                          
    25                          
    26                          !macro ayWriteX .dev, .reg {
    27                                  lda #.reg
    28                                  sta IO_PORT_BASE_ADDRESS | AY_IO_PORT | AY_ADDR | .dev
    29                                  stx IO_PORT_BASE_ADDRESS | AY_IO_PORT | AY_WRITE | .dev
    30                          }
    31                          
    32                          !macro ayWriteA .dev, .reg {
    33                                  ldx #.reg
    34                                  stx IO_PORT_BASE_ADDRESS | AY_IO_PORT | AY_ADDR | .dev
    35                                  sta IO_PORT_BASE_ADDRESS | AY_IO_PORT | AY_WRITE | .dev
    36                          }
    37                          
    38                          !macro ayPlayNote .dev, .chan, .freq {
    39                                  !if .freq <= 0 {
    40                                          .val = 0
    41                                  } else {
    42                                          .val = AY_CLOCK_FREQ / (32.0 * .freq)
    43                                  }
    44                                  +ayWrite .dev, AY_CHA_TONE_L + (.chan * 2), <.val
    45                                  +ayWrite .dev, AY_CHA_TONE_H + (.chan * 2), >.val
    46                          }
    47                          
    48                          !macro ayToneWord .freq {
    49                                  !word (AY_CLOCK_FREQ / (32.0 * .freq))
    50                          }
    51                          
    52                          !macro ayToneByteL .freq {
    53                                  !byte <(AY_CLOCK_FREQ / (32.0 * .freq))
    54                          }
    55                          
    56                          !macro ayToneByteH .freq {
    57                                  !byte >(AY_CLOCK_FREQ / (32.0 * .freq))
    58                          }
    59                          
    60                          
    61                          !macro ayToneEnable .dev, .chan {
    62                                  +ayRead .dev, AY_ENABLES
    63                                  and #!($01 << .chan)
    64                                  +ayWriteA .dev, AY_ENABLES
    65                          }
    66                          
    67                          !macro ayToneDisable .dev, .chan {
    68                                  +ayRead .dev, AY_ENABLES
    69                                  ora #($01 << .chan)
    70                                  +ayWriteA .dev, AY_ENABLES
    71                          }
    72                          
    73                          !macro ayNoiseEnable .dev, .chan {
    74                                  +ayRead .dev, AY_ENABLES
    75                                  eor #($08 << .chan)
    76                                  +ayWriteA .dev, AY_ENABLES
    77                          }
    78                          
    79                          !macro ayNoiseDisable .dev, .chan {
    80                                  +ayRead .dev, AY_ENABLES
    81                                  ora #($08 << .chan)
    82                                  +ayWriteA .dev, AY_ENABLES
    83                          }
    84                          
    85                          !macro aySetVolume .dev, .chan, .vol {
    86                                  +ayWrite .dev, (AY_CHA_AMPL + .chan), (.vol >> 4)
    87                          }
    88                          
    89                          !macro aySetVolumeEnvelope .dev, .chan {
    90                                  +ayWrite .dev, (AY_CHA_AMPL + .chan), $10
    91                          }
    92                          
    93                          !macro aySetEnvelopePeriod .dev, .period {
    94                                  +ayWrite .dev, AY_ENV_PERIOD_L, <.period
    95                                  +ayWrite .dev, AY_ENV_PERIOD_H, >.period
    96                          }
    97                          
    98                          !macro aySetEnvShape .dev, .shape {
    99                                  +ayWrite .dev, AY_ENV_SHAPE, .shape
   100                          }
   101                          
   102                          !macro aySetNoise .dev, .freq {
   103                                  +ayWrite .dev, AY_ENV_SHAPE, .freq >> 3
   104                          }
   105                          
   106                          !macro ayStop .dev, .chan {
   107                                  +ayPlayNote .dev, .chan, 0
   108                          }

; ******** Source: ../lib\sfx\ay3891x.asm
    10                          
    11                          
    12                          
    13                          !ifndef AY_IO_PORT { AY_IO_PORT = $40
    14                                  !warn "AY_IO_PORT not provided. Defaulting to ", AY_IO_PORT
    15                          }
    16                          
    17                          HAVE_AY3891X = 1
    18                          
    19                          ; -------------------------
    20                          ; Constants
    21                          ; -------------------------
    22                          AY_PSG0 = $00
    23                          AY_PSG1 = $04
    24                          
    25                          ; IO Ports
    26                          AY_S0 = IO_PORT_BASE_ADDRESS | AY_IO_PORT | AY_PSG0
    27                          AY_S1 = IO_PORT_BASE_ADDRESS | AY_IO_PORT | AY_PSG1
    28                          
    29                          AY_INACTIVE = $03
    30                          AY_READ     = $02
    31                          AY_WRITE    = $01
    32                          AY_ADDR     = $00
    33                          
    34                          AY_S0_READ  = AY_S0 | AY_READ
    35                          AY_S0_WRITE = AY_S0 | AY_WRITE
    36                          AY_S0_ADDR  = AY_S0 | AY_ADDR
    37                          
    38                          AY_S1_READ  = AY_S1 | AY_READ
    39                          AY_S1_WRITE = AY_S1 | AY_WRITE
    40                          AY_S1_ADDR  = AY_S1 | AY_ADDR
    41                          
    42                          ; Registers
    43                          AY_R0 = 0
    44                          AY_R1 = 1
    45                          AY_R2 = 2
    46                          AY_R3 = 3
    47                          AY_R4 = 4
    48                          AY_R5 = 5
    49                          AY_R6 = 6
    50                          AY_R7 = 7
    51                          AY_R8 = 8
    52                          AY_R9 = 9
    53                          AY_R10 = 10
    54                          AY_R11 = 11
    55                          AY_R12 = 12
    56                          AY_R13 = 13
    57                          AY_R14 = 14
    58                          AY_R15 = 15
    59                          AY_R16 = 16
    60                          AY_R17 = 17
    61                          
    62                          AY_CHA = 0
    63                          AY_CHB = 1
    64                          AY_CHC = 2
    65                          AY_CHN = 3
    66                          
    67                          AY_CHA_TONE_L   = AY_R0
    68                          AY_CHA_TONE_H   = AY_R1
    69                          AY_CHB_TONE_L   = AY_R2
    70                          AY_CHB_TONE_H   = AY_R3
    71                          AY_CHC_TONE_L   = AY_R4
    72                          AY_CHC_TONE_H   = AY_R5
    73                          AY_NOISE_GEN    = AY_R6
    74                          AY_ENABLES      = AY_R7
    75                          AY_CHA_AMPL     = AY_R8
    76                          AY_CHB_AMPL     = AY_R9
    77                          AY_CHC_AMPL     = AY_R10
    78                          AY_ENV_PERIOD_L = AY_R11
    79                          AY_ENV_PERIOD_H = AY_R12
    80                          AY_ENV_SHAPE    = AY_R13
    81                          AY_PORTA        = AY_R14
    82                          AY_PORTB        = AY_R15
    83                          
    84                          AY_ENV_SHAPE_CONTINUE  = $08
    85                          AY_ENV_SHAPE_ATTACK    = $04
    86                          AY_ENV_SHAPE_ALTERNATE = $02
    87                          AY_ENV_SHAPE_HOLD      = $01
    88                          
    89                          ;  /\  /\  /\  /\  /\ 
    90                          ; /  \/  \/  \/  \/  \
    91                          AY_ENV_SHAPE_TRIANGLE     = (AY_ENV_SHAPE_CONTINUE | AY_ENV_SHAPE_ATTACK | AY_ENV_SHAPE_ALTERNATE)
    92                          
    93                          ;  /------------------
    94                          ; /
    95                          AY_ENV_SHAPE_FADE_IN      = (AY_ENV_SHAPE_CONTINUE | AY_ENV_SHAPE_ATTACK | AY_ENV_SHAPE_HOLD)
    96                          
    97                          ; \
    98                          ;  \__________________
    99                          AY_ENV_SHAPE_FADE_OUT     = (AY_ENV_SHAPE_CONTINUE | AY_ENV_SHAPE_HOLD)
   100                          
   101                          ; \ |\ |\ |\ |\ |\ |\ |
   102                          ;  \| \| \| \| \| \| \|
   103                          AY_ENV_SHAPE_SAW1         = (AY_ENV_SHAPE_CONTINUE)
   104                          
   105                          ;  /| /| /| /| /| /| /|
   106                          ; / |/ |/ |/ |/ |/ |/ |
   107                          AY_ENV_SHAPE_SAW2         = (AY_ENV_SHAPE_CONTINUE | AY_ENV_SHAPE_ATTACK)
   108                          
   109                          ;  /|
   110                          ; / |__________________
   111                          AY_ENV_SHAPE_FADE_IN_STOP = (AY_ENV_SHAPE_ATTACK)
   112                          
   113                          
   114                          AY_CLOCK_FREQ   = 2000000
   115                          
   116                          ayInit:
   117                                  ; disable everything
   118  e158 a9078d407fa9ff8d...        +ayWrite AY_PSG0, AY_ENABLES, $ff
   119  e162 a9078d447fa9ff8d...        +ayWrite AY_PSG1, AY_ENABLES, $ff
   120                          
   121  e16c a9088d407fa9008d...        +aySetVolume AY_PSG0, AY_CHA, 0
   122  e176 a9098d407fa9008d...        +aySetVolume AY_PSG0, AY_CHB, 0
   123  e180 a90a8d407fa9008d...        +aySetVolume AY_PSG0, AY_CHC, 0
   124                          
   125  e18a a9008d407fa9008d...        +ayPlayNote AY_PSG0, AY_CHA, 0
   126  e19e a9028d407fa9008d...        +ayPlayNote AY_PSG0, AY_CHB, 0
   127  e1b2 a9048d407fa9008d...        +ayPlayNote AY_PSG0, AY_CHC, 0
   128                          
   129  e1c6 a90b8d407fa9008d...        +aySetEnvelopePeriod AY_PSG0, 0
   130  e1da a90d8d407fa9008d...        +aySetEnvShape AY_PSG0, 0
   131  e1e4 a90d8d407fa9008d...        +aySetNoise  AY_PSG0, 0
   132                          
   133  e1ee a9088d447fa9008d...        +aySetVolume AY_PSG1, AY_CHA, 0
   134  e1f8 a9098d447fa9008d...        +aySetVolume AY_PSG1, AY_CHB, 0
   135  e202 a90a8d447fa9008d...        +aySetVolume AY_PSG1, AY_CHC, 0
   136                          
   137  e20c a9008d447fa9008d...        +ayPlayNote AY_PSG1, AY_CHA, 0
   138  e220 a9028d447fa9008d...        +ayPlayNote AY_PSG1, AY_CHB, 0
   139  e234 a9048d447fa9008d...        +ayPlayNote AY_PSG1, AY_CHC, 0
   140                          
   141  e248 a90b8d447fa9008d...        +aySetEnvelopePeriod AY_PSG1, 0
   142  e25c a90d8d447fa9008d...        +aySetEnvShape AY_PSG1, 0
   143  e266 a90d8d447fa9008d...        +aySetNoise  AY_PSG1, 0
   144  e270 60                         rts
   145                          
   146                          ; Note frequencies from https://pages.mtu.edu/~suits/notefreqs.html
   147                          
   148                          NOTE_FREQ_C0  = 16.35
   149                          NOTE_FREQ_CS0 = 17.32
   150                          NOTE_FREQ_D0  = 18.35
   151                          NOTE_FREQ_DS0 = 19.45
   152                          NOTE_FREQ_E0  = 20.6
   153                          NOTE_FREQ_F0  = 21.83
   154                          NOTE_FREQ_FS0 = 23.12
   155                          NOTE_FREQ_G0  = 24.5
   156                          NOTE_FREQ_GS0 = 25.96
   157                          NOTE_FREQ_A0  = 27.5
   158                          NOTE_FREQ_AS0 = 29.14
   159                          NOTE_FREQ_B0  = 30.87
   160                          NOTE_FREQ_C1  = 32.7
   161                          NOTE_FREQ_CS1 = 34.65
   162                          NOTE_FREQ_D1  = 36.71
   163                          NOTE_FREQ_DS1 = 38.89
   164                          NOTE_FREQ_E1  = 41.2
   165                          NOTE_FREQ_F1  = 43.65
   166                          NOTE_FREQ_FS1 = 46.25
   167                          NOTE_FREQ_G1  = 49
   168                          NOTE_FREQ_GS1 = 51.91
   169                          NOTE_FREQ_A1  = 55
   170                          NOTE_FREQ_AS1 = 58.27
   171                          NOTE_FREQ_B1  = 61.74
   172                          NOTE_FREQ_C2  = 65.41
   173                          NOTE_FREQ_CS2 = 69.3
   174                          NOTE_FREQ_D2  = 73.42
   175                          NOTE_FREQ_DS2 = 77.78
   176                          NOTE_FREQ_E2  = 82.41
   177                          NOTE_FREQ_F2  = 87.31
   178                          NOTE_FREQ_FS2 = 92.5
   179                          NOTE_FREQ_G2  = 98
   180                          NOTE_FREQ_GS2 = 103.83
   181                          NOTE_FREQ_A2  = 110
   182                          NOTE_FREQ_AS2 = 116.54
   183                          NOTE_FREQ_B2  = 123.47
   184                          NOTE_FREQ_C3  = 130.81
   185                          NOTE_FREQ_CS3 = 138.59
   186                          NOTE_FREQ_D3  = 146.83
   187                          NOTE_FREQ_DS3 = 155.56
   188                          NOTE_FREQ_E3  = 164.81
   189                          NOTE_FREQ_F3  = 174.61
   190                          NOTE_FREQ_FS3 = 185
   191                          NOTE_FREQ_G3  = 196
   192                          NOTE_FREQ_GS3 = 207.65
   193                          NOTE_FREQ_A3  = 220
   194                          NOTE_FREQ_AS3 = 233.08
   195                          NOTE_FREQ_B3  = 246.94
   196                          NOTE_FREQ_C4  = 261.63
   197                          NOTE_FREQ_CS4 = 277.18
   198                          NOTE_FREQ_D4  = 293.66
   199                          NOTE_FREQ_DS4 = 311.13
   200                          NOTE_FREQ_E4  = 329.63
   201                          NOTE_FREQ_F4  = 349.23
   202                          NOTE_FREQ_FS4 = 369.99
   203                          NOTE_FREQ_G4  = 392
   204                          NOTE_FREQ_GS4 = 415.3
   205                          NOTE_FREQ_A4  = 440
   206                          NOTE_FREQ_AS4 = 466.16
   207                          NOTE_FREQ_B4  = 493.88
   208                          NOTE_FREQ_C5  = 523.25
   209                          NOTE_FREQ_CS5 = 554.37
   210                          NOTE_FREQ_D5  = 587.33
   211                          NOTE_FREQ_DS5 = 622.25
   212                          NOTE_FREQ_E5  = 659.25
   213                          NOTE_FREQ_F5  = 698.46
   214                          NOTE_FREQ_FS5 = 739.99
   215                          NOTE_FREQ_G5  = 783.99
   216                          NOTE_FREQ_GS5 = 830.61
   217                          NOTE_FREQ_A5  = 880
   218                          NOTE_FREQ_AS5 = 932.33
   219                          NOTE_FREQ_B5  = 987.77
   220                          NOTE_FREQ_C6  = 1046.5
   221                          NOTE_FREQ_CS6 = 1108.73
   222                          NOTE_FREQ_D6  = 1174.66
   223                          NOTE_FREQ_DS6 = 1244.51
   224                          NOTE_FREQ_E6  = 1318.51
   225                          NOTE_FREQ_F6  = 1396.91
   226                          NOTE_FREQ_FS6 = 1479.98
   227                          NOTE_FREQ_G6  = 1567.98
   228                          NOTE_FREQ_GS6 = 1661.22
   229                          NOTE_FREQ_A6  = 1760
   230                          NOTE_FREQ_AS6 = 1864.66
   231                          NOTE_FREQ_B6  = 1975.53
   232                          NOTE_FREQ_C7  = 2093
   233                          NOTE_FREQ_CS7 = 2217.46
   234                          NOTE_FREQ_D7  = 2349.32
   235                          NOTE_FREQ_DS7 = 2489.02
   236                          NOTE_FREQ_E7  = 2637.02
   237                          NOTE_FREQ_F7  = 2793.83
   238                          NOTE_FREQ_FS7 = 2959.96
   239                          NOTE_FREQ_G7  = 3135.96
   240                          NOTE_FREQ_GS7 = 3322.44
   241                          NOTE_FREQ_A7  = 3520
   242                          NOTE_FREQ_AS7 = 3729.31
   243                          NOTE_FREQ_B7  = 3951.07
   244                          NOTE_FREQ_C8  = 4186.01
   245                          NOTE_FREQ_CS8 = 4434.92
   246                          NOTE_FREQ_D8  = 4698.63
   247                          NOTE_FREQ_DS8 = 4978.03
   248                          NOTE_FREQ_E8  = 5274.04
   249                          NOTE_FREQ_F8  = 5587.65
   250                          NOTE_FREQ_FS8 = 5919.91
   251                          NOTE_FREQ_G8  = 6271.93
   252                          NOTE_FREQ_GS8 = 6644.88
   253                          NOTE_FREQ_A8  = 7040
   254                          NOTE_FREQ_AS8 = 7458.62
   255                          NOTE_FREQ_B8  = 7902.13

; ******** Source: kernel.asm
   153                          
   154                          }
   155                          
   156                          !ifndef HBC56_DISABLE_TMS9918 {
   157                                  !ifndef TMS_MODEL { TMS_MODEL = 9918 }

; ******** Source: ../lib\gfx\tms9918.asm
     1                          ; 6502 - TMS9918 VDP
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          

; ******** Source: ../lib\hbc56.inc
     1                          ; 6502 - HBC-56
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          ;
    10                          
    11                          ; Base address of the 256 IO port memory range
    12                          IO_PORT_BASE_ADDRESS    = $7f00
    13                          
    14                          
    15                          ; -------------------------
    16                          ; ASCII constants
    17                          ; -------------------------
    18                          ASCII_RETURN    = $0A
    19                          ASCII_CR        = $0D
    20                          ASCII_BACKSPACE = $08
    21                          ASCII_BELL      = $07

; ******** Source: ../lib\gfx\tms9918.asm
    10                          
    11                          
    12                          !ifndef HAVE_MATH_INC { !src "ut/math.inc" }

; ******** Source: ../lib\gfx\tms9918.inc
     1                          ; 6502 - TMS9918 VDP Macros
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          
    10                          
    11                          
    12                          
    13                          ; -----------------------------------------------------------------------------
    14                          ; tmsWaitReg: Not sure how much delay we need so make a macro for now
    15                          ; -----------------------------------------------------------------------------
    16                          !macro tmsWaitReg {
    17                                  jsr _tmsWaitReg
    18                          }
    19                          
    20                          ; -----------------------------------------------------------------------------
    21                          ; tmsWaitData: Not sure how much delay we need so make a macro for now
    22                          ; -----------------------------------------------------------------------------
    23                          !macro tmsWaitData {
    24                                  jsr _tmsWaitData
    25                          }
    26                          
    27                          ; -----------------------------------------------------------------------------
    28                          ; tmsSetAddressWrite: Set an address in the TMS9918
    29                          ; -----------------------------------------------------------------------------
    30                          !macro tmsSetAddressWrite .addr {
    31                                  +tmsSetAddressRead ($4000 | .addr)
    32                          }
    33                          
    34                          ; -----------------------------------------------------------------------------
    35                          ; tmsSetAddressRead: Set an address to read from the TMS9918
    36                          ; -----------------------------------------------------------------------------
    37                          !macro tmsSetAddressRead .addr {
    38                                  php
    39                                  sei             ; we can't be interrupted here
    40                                  lda #<(.addr)
    41                                  sta TMS9918_REG
    42                                  +tmsWaitReg
    43                                  lda #>(.addr)
    44                                  sta TMS9918_REG
    45                                  +tmsWaitReg
    46                                  plp
    47                          }
    48                          
    49                          ; -----------------------------------------------------------------------------
    50                          ; tmsGet: Get a byte of data from the TMS9918
    51                          ; -----------------------------------------------------------------------------
    52                          !macro tmsGet {
    53                                  lda TMS9918_RAM
    54                                  +tmsWaitData
    55                          }
    56                          
    57                          ; -----------------------------------------------------------------------------
    58                          ; tmsPut: Send a byte of data to the TMS9918
    59                          ; -----------------------------------------------------------------------------
    60                          !macro tmsPut .byte {
    61                                  lda #(.byte & 0xff)
    62                                  +tmsPut
    63                          }
    64                          
    65                          
    66                          ; -----------------------------------------------------------------------------
    67                          ; tmsPut: Send a byte (A) of data to the TMS9918
    68                          ; -----------------------------------------------------------------------------
    69                          !macro tmsPut {
    70                                  sta TMS9918_RAM
    71                                  +tmsWaitData
    72                          }
    73                          
    74                          ; -----------------------------------------------------------------------------
    75                          ; tmsSetColor: Set current fg/bg color
    76                          ; -----------------------------------------------------------------------------
    77                          !macro tmsSetColor .color {
    78                                  lda #.color
    79                                  jsr tmsSetBackground
    80                          }
    81                          
    82                          ; -----------------------------------------------------------------------------
    83                          ; tmsSetColorFgBg: Set current fg/bg color
    84                          ; -----------------------------------------------------------------------------
    85                          !macro tmsSetColorFgBg .fg, .bg {
    86                                  +tmsColorFgBg .fg, .bg
    87                                  jsr tmsSetBackground
    88                          }
    89                          
    90                          ; -----------------------------------------------------------------------------
    91                          ; byteTmsColorFgBg: Output a data byte
    92                          ; -----------------------------------------------------------------------------
    93                          !macro byteTmsColorFgBg .fg, .bg {
    94                          !byte (.fg << 4 | .bg)
    95                          }
    96                          
    97                          
    98                          ; -----------------------------------------------------------------------------
    99                          ; tmsDisableOutput: Disable the TMS9918 output
   100                          ; -----------------------------------------------------------------------------
   101                          !macro tmsDisableOutput {
   102                                  lda #TMS_R1_DISP_ACTIVE
   103                                  jsr tmsReg1ClearFields
   104                          }
   105                          
   106                          ; -----------------------------------------------------------------------------
   107                          ; tmsEnableOutput: Enable the TMS9918 output
   108                          ; -----------------------------------------------------------------------------
   109                          !macro tmsEnableOutput {
   110                                  lda #TMS_R1_DISP_ACTIVE
   111                                  jsr tmsReg1SetFields
   112                          }
   113                          
   114                          ; -
   115                          !macro tmsEnableInterrupts {
   116                                  lda #TMS_R1_INT_ENABLE
   117                                  jsr tmsReg1SetFields
   118                          }
   119                          
   120                          !macro tmsDisableInterrupts {
   121                                  lda #TMS_R1_INT_ENABLE
   122                                  jsr tmsReg1ClearFields
   123                          }
   124                          
   125                          !macro tmsConsoleOut .char {
   126                                  lda #.char
   127                                  jsr tmsConsoleOut
   128                          }
   129                          
   130                          
   131                          ; -----------------------------------------------------------------------------
   132                          ; tmsConsolePrintAddr: Print text to console
   133                          ; -----------------------------------------------------------------------------
   134                          ; Inputs:
   135                          ;  textAddr: Address of null-terminated string to print
   136                          ; -----------------------------------------------------------------------------
   137                          !macro tmsConsolePrintAddr .textAddr {
   138                                  lda #<.textAddr
   139                                  sta STR_ADDR_L
   140                                  lda #>.textAddr
   141                                  sta STR_ADDR_H
   142                                  jsr tmsConsolePrint        
   143                          }
   144                          
   145                          ; -----------------------------------------------------------------------------
   146                          ; tmsConsolePrint: Print immediate text to console
   147                          ; -----------------------------------------------------------------------------
   148                          ; Inputs:
   149                          ;  str: String to print
   150                          ; -----------------------------------------------------------------------------
   151                          !macro tmsConsolePrint .str {
   152                                  jmp .afterText
   153                          .textAddr
   154                                  !text .str,0
   155                          .afterText        
   156                                  +tmsConsolePrintAddr .textAddr
   157                          }
   158                          
   159                          ; -----------------------------------------------------------------------------
   160                          ; +tmsColorFgBg: Set A to the given FG / BG color
   161                          ; -----------------------------------------------------------------------------
   162                          !macro tmsColorFgBg .fg, .bg {
   163                                  lda #(.fg << 4 | .bg)
   164                          }
   165                          
   166                          ; -----------------------------------------------------------------------------
   167                          ; tmsReadStatus: Read status - clear interrupt
   168                          ; -----------------------------------------------------------------------------
   169                          !macro tmsReadStatus  {
   170                                  bit TMS9918_REG
   171                          }
   172                          
   173                          ; -----------------------------------------------------------------------------
   174                          ; tmsSendData: Send # bytes from .sourceAddr to tms9918 data port
   175                          ; -----------------------------------------------------------------------------
   176                          !macro tmsSendData .sourceAddr, .numBytes {
   177                                  lda #<.sourceAddr
   178                                  sta TMS_TMP_ADDRESS
   179                                  lda #>.sourceAddr
   180                                  sta TMS_TMP_ADDRESS + 1
   181                          
   182                                  !if .numBytes < 256 {
   183                                          ldx #.numBytes
   184                                          jsr tmsSendBytes
   185                                  } else {
   186                                          !do while .numBytes > 0 {
   187                                                  !if .numBytes > 255 {
   188                                                          ldx #0
   189                                                          !set .numBytes = .numBytes - 256
   190                                                  } else {
   191                                                          ldx #.numBytes
   192                                                          !set .numBytes = 0
   193                                                  }
   194                                                  jsr tmsSendBytes
   195                                                  inc TMS_TMP_ADDRESS + 1
   196                                          }
   197                                  }
   198                          
   199                          }
   200                          
   201                          ; -----------------------------------------------------------------------------
   202                          ; tmsSendDataRpt: Send # bytes from .sourceAddr to tms9918 data port .rpt times
   203                          ; -----------------------------------------------------------------------------
   204                          !macro tmsSendDataRpt .sourceAddr, .numBytes, .rpt {
   205                                  lda #<.sourceAddr
   206                                  sta TMS_TMP_ADDRESS
   207                                  lda #>.sourceAddr
   208                                  sta TMS_TMP_ADDRESS + 1
   209                          
   210                                  !if .numBytes < 256 {
   211                                          !if .rpt < 5 {
   212                                                  !for i,1,.rpt {
   213                                                          ldx #.numBytes
   214                                                          jsr tmsSendBytes
   215                                                  }
   216                                          } else {
   217                                                  lda #.rpt
   218                                                  sta TMS9918_TMP_BUFFER
   219                          -
   220                                                  ldx #.numBytes
   221                                                  jsr tmsSendBytes
   222                                                  dec TMS9918_TMP_BUFFER
   223                                                  bne -
   224                                          }
   225                                  } else {
   226                                          !error "tmsSendDataRpt supports <256 bytes only"
   227                                  }
   228                          }
   229                          
   230                          
   231                          ; -----------------------------------------------------------------------------
   232                          ; tmsPutRpt: Send value .rpt times
   233                          ; -----------------------------------------------------------------------------
   234                          !macro tmsPutRpt .value, .rpt {
   235                                  ldx #.rpt
   236                                  lda #.value
   237                          -
   238                                  +tmsPut
   239                                  dex
   240                                  bne -
   241                          }
   242                          
   243                          !macro tmsPutSeq .from, .count {
   244                                  lda #.from
   245                          -
   246                                  +tmsPut
   247                                  inc
   248                                  cmp #<(.from + .count)
   249                                  bne -
   250                          }
   251                          
   252                          !macro tmsSetSourceAddressInd .addr {
   253                                  lda .addr
   254                                  sta TMS_TMP_ADDRESS
   255                                  lda .addr + 1
   256                                  sta TMS_TMP_ADDRESS + 1
   257                          }
   258                          
   259                          !macro tmsSetSourceAddressIndOffset .addr, .offset {
   260                                  clc
   261                                  lda .addr
   262                                  adc #<.offset
   263                                  sta TMS_TMP_ADDRESS
   264                                  lda .addr + 1
   265                                  adc #>.offset
   266                                  sta TMS_TMP_ADDRESS + 1
   267                          }
   268                          
   269                          
   270                          !macro tmsSendBytes .bytes {
   271                                  ldx #.bytes
   272                                  jsr tmsSendBytes
   273                          }
   274                          
   275                          
   276                          ; -----------------------------------------------------------------------------
   277                          ; tmsSetAddrPattTable: Initialise address for font table
   278                          ; -----------------------------------------------------------------------------
   279                          !macro tmsSetAddrPattTable {
   280                                  +tmsSetAddrPattTable 0
   281                          }
   282                          
   283                          ; -----------------------------------------------------------------------------
   284                          ; tmsSetAddrPattTable: Initialise address for pattern table
   285                          ; -----------------------------------------------------------------------------
   286                          !macro tmsSetAddrPattTable .ind {
   287                                  +tmsSetAddressWrite TMS_VRAM_PATT_ADDRESS + (8 * .ind)
   288                          }
   289                          
   290                          ; -----------------------------------------------------------------------------
   291                          ; tmsSetAddrPattTable: Initialise address for pattern table
   292                          ; -----------------------------------------------------------------------------
   293                          !macro tmsSetAddrPattTable .ind, .row {
   294                                  +tmsSetAddressWrite TMS_VRAM_PATT_ADDRESS + (8 * .ind) + .row
   295                          }
   296                          
   297                          ; -----------------------------------------------------------------------------
   298                          ; tmsSetAddrPattTableIIBank0: Initialise address for pattern table
   299                          ; -----------------------------------------------------------------------------
   300                          !macro tmsSetAddrPattTableIIBank0 .ind {
   301                                  +tmsSetAddrPattTable .ind
   302                          }
   303                          
   304                          ; -----------------------------------------------------------------------------
   305                          ; tmsSetAddrPattTableIIBank1: Initialise address for pattern table
   306                          ; -----------------------------------------------------------------------------
   307                          !macro tmsSetAddrPattTableIIBank1 .ind {
   308                                  +tmsSetAddrPattTable 256 + .ind
   309                          }
   310                          
   311                          ; -----------------------------------------------------------------------------
   312                          ; tmsSetAddrPattTableIIBank2: Initialise address for pattern table
   313                          ; -----------------------------------------------------------------------------
   314                          !macro tmsSetAddrPattTableIIBank2 .ind {
   315                                  +tmsSetAddrPattTable 512 + .ind
   316                          }
   317                          
   318                          ; -----------------------------------------------------------------------------
   319                          ; tmsSetAddrPattTableRead: Initialise address for pattern table to read
   320                          ; -----------------------------------------------------------------------------
   321                          !macro tmsSetAddrPattTableRead .ind {
   322                                  +tmsSetAddressRead TMS_VRAM_PATT_ADDRESS + (8 * .ind)
   323                          }
   324                          
   325                          ; -----------------------------------------------------------------------------
   326                          ; tmsSetAddrPattTableRowRead: Initialise address for pattern table to read
   327                          ; -----------------------------------------------------------------------------
   328                          !macro tmsSetAddrPattTableRead .ind, .row {
   329                                  +tmsSetAddressRead TMS_VRAM_PATT_ADDRESS + (8 * .ind) + .row
   330                          }
   331                          
   332                          ; -----------------------------------------------------------------------------
   333                          ; tmsUpdateFont: Update the pattern table with a given font
   334                          ; -----------------------------------------------------------------------------
   335                          !macro tmsUpdateFont .fontAddr {
   336                                  +tmsSetAddrPattTable 32
   337                                  +tmsSendData .fontAddr, $300
   338                          }
   339                          
   340                          ; -----------------------------------------------------------------------------
   341                          ; tmsSetAddrNameTable: Initialise address for base (text) table
   342                          ; -----------------------------------------------------------------------------
   343                          !macro tmsSetAddrNameTable {
   344                                  +tmsSetAddressWrite TMS_VRAM_NAME_ADDRESS
   345                          }
   346                          
   347                          ; -----------------------------------------------------------------------------
   348                          ; tmsSetAddrColorTable: Initialise address for color table
   349                          ; -----------------------------------------------------------------------------
   350                          !macro tmsSetAddrColorTable {
   351                                  +tmsSetAddressWrite TMS_VRAM_COLOR_ADDRESS
   352                          }
   353                          
   354                          ; -----------------------------------------------------------------------------
   355                          ; tmsSetAddrColorTable: Initialise address for color table index
   356                          ; -----------------------------------------------------------------------------
   357                          !macro tmsSetAddrColorTable .ind {
   358                                  +tmsSetAddressWrite TMS_VRAM_COLOR_ADDRESS + .ind
   359                          }
   360                          
   361                          ; -----------------------------------------------------------------------------
   362                          ; tmsSetAddrColorTableII: Initialise address for color table index (mode II)
   363                          ; -----------------------------------------------------------------------------
   364                          !macro tmsSetAddrColorTableII .ind {
   365                                  +tmsSetAddressWrite TMS_VRAM_COLOR_ADDRESS + .ind * 8
   366                          }
   367                          
   368                          ; -----------------------------------------------------------------------------
   369                          ; tmsSetAddrColorTableIIBank0: Initialise address for color table index (mode II)
   370                          ; -----------------------------------------------------------------------------
   371                          !macro tmsSetAddrColorTableIIBank0 .ind {
   372                                  +tmsSetAddrColorTableII .ind
   373                          }
   374                          
   375                          ; -----------------------------------------------------------------------------
   376                          ; tmsSetAddrColorTableIIBank1: Initialise address for color table index (mode II)
   377                          ; -----------------------------------------------------------------------------
   378                          !macro tmsSetAddrColorTableIIBank1 .ind {
   379                                  +tmsSetAddrColorTableII 256 + .ind
   380                          }
   381                          
   382                          ; -----------------------------------------------------------------------------
   383                          ; tmsSetAddrColorTableIIBank2: Initialise address for color table index (mode II)
   384                          ; -----------------------------------------------------------------------------
   385                          !macro tmsSetAddrColorTableIIBank2 .ind {
   386                                  +tmsSetAddrColorTableII 512 + .ind
   387                          }
   388                          
   389                          ; -----------------------------------------------------------------------------
   390                          ; tmsSetAddrSpriteAttrTable: Initialise address for sprite attributes table
   391                          ; -----------------------------------------------------------------------------
   392                          !macro tmsSetAddrSpriteAttrTable {
   393                                  +tmsSetAddrSpriteAttrTable 0
   394                          }
   395                          
   396                          ; -----------------------------------------------------------------------------
   397                          ; tmsSetAddrSpriteAttrTable: Initialise address for sprite attributes table
   398                          ; -----------------------------------------------------------------------------
   399                          !macro tmsSetAddrSpriteAttrTable .index {
   400                                  +tmsSetAddressWrite TMS_VRAM_SPRITE_ATTR_ADDRESS + .index * 4
   401                          }
   402                          
   403                          ; -----------------------------------------------------------------------------
   404                          ; tmsSetAddrSpritePattTable: Initialise address for sprite pattern table
   405                          ; -----------------------------------------------------------------------------
   406                          !macro tmsSetAddrSpritePattTable {
   407                                  +tmsSetAddrSpritePattTable 0
   408                          }
   409                          
   410                          ; -----------------------------------------------------------------------------
   411                          ; tmsSetAddrSpritePattTable: Initialise address for sprite pattern table
   412                          ; -----------------------------------------------------------------------------
   413                          !macro tmsSetAddrSpritePattTable .index {
   414                                  +tmsSetAddressWrite TMS_VRAM_SPRITE_PATT_ADDRESS + .index * 8
   415                          }
   416                          
   417                          
   418                          ; -----------------------------------------------------------------------------
   419                          ; tmsCreateSpritePattern: Create a sprite pattern (.spriteDataAddr is 8 bytes)
   420                          ; -----------------------------------------------------------------------------
   421                          !macro tmsCreateSpritePattern .pattInd, .spriteDataAddr {
   422                          
   423                                  
   424                          
   425                                  ; sprite pattern table
   426                                  +tmsSetAddrSpritePattTable .pattInd
   427                          
   428                                  ldx #0
   429                          -
   430                                  lda .spriteDataAddr,x
   431                                  +tmsPut
   432                                  inx
   433                                  cpx #8
   434                          
   435                                  
   436                          
   437                                  bne -
   438                          }
   439                          
   440                          ; -----------------------------------------------------------------------------
   441                          ; tmsCreateSpritePatternQuad: Create a (size 1) sprite pattern 
   442                          ;   (.spriteDataAddr is 32 bytes)
   443                          ; -----------------------------------------------------------------------------
   444                          !macro tmsCreateSpritePatternQuad .pattInd, .spriteDataAddr {
   445                          
   446                                  
   447                          
   448                                  ; sprite pattern table
   449                                  +tmsSetAddrSpritePattTable .pattInd * 4
   450                          
   451                                  ldx #0
   452                          -
   453                                  lda .spriteDataAddr,x
   454                                  +tmsPut 
   455                                  inx
   456                                  cpx #32
   457                          
   458                                  
   459                          
   460                                  bne -
   461                          }
   462                          
   463                          
   464                          !macro tmsCreateSpritePatternImm .ind, .b0, .b1, .b2, .b3, .b4, .b5, .b6, .b7 {
   465                          
   466                                  ; sprite pattern table
   467                                  +tmsSetAddrSpritePattTable .ind
   468                                  +tmsPut .b0
   469                                  +tmsPut .b2
   470                                  +tmsPut .b2
   471                                  +tmsPut .b3
   472                                  +tmsPut .b4
   473                                  +tmsPut .b5
   474                                  +tmsPut .b6
   475                                  +tmsPut .b7
   476                          }
   477                          
   478                          !macro tmsCreatePatternImm .ind, .b0, .b1, .b2, .b3, .b4, .b5, .b6, .b7 {
   479                          
   480                                  ; sprite pattern table
   481                                  +tmsSetAddrPattTable .ind
   482                                  +tmsPut .b0
   483                                  +tmsPut .b2
   484                                  +tmsPut .b2
   485                                  +tmsPut .b3
   486                                  +tmsPut .b4
   487                                  +tmsPut .b5
   488                                  +tmsPut .b6
   489                                  +tmsPut .b7
   490                          }
   491                          
   492                          
   493                          ; -----------------------------------------------------------------------------
   494                          ; tmsCreateSprite: Create a sprite
   495                          ; -----------------------------------------------------------------------------
   496                          !macro tmsCreateSprite .ind, .pattInd, .xPos, .yPos, .color {
   497                          
   498                                  ; sprite attr table
   499                                  +tmsSetAddrSpriteAttrTable .ind
   500                          
   501                                  +tmsPut .yPos
   502                                  +tmsPut .xPos
   503                                  +tmsPut .pattInd
   504                                  +tmsPut .color
   505                          }
   506                          
   507                          ; -----------------------------------------------------------------------------
   508                          ; tmsSpritePos: Set a sprite position
   509                          ; -----------------------------------------------------------------------------
   510                          !macro tmsSpritePos .ind, .xPos, .yPos {
   511                                  
   512                          
   513                                  ; sprite attr table
   514                                  +tmsSetAddrSpriteAttrTable .ind
   515                          
   516                                  +tmsPut .yPos
   517                                  +tmsPut .xPos        
   518                          }
   519                          
   520                          
   521                          ; -----------------------------------------------------------------------------
   522                          ; tmsSetLastSprite: Mark a sprite as the last sprite (set next ypos to )
   523                          ; -----------------------------------------------------------------------------
   524                          !macro tmsSetLastSprite .ind {
   525                                  +tmsSpritePos .ind + 1, 0, $d0
   526                          }
   527                          
   528                          
   529                          ; -----------------------------------------------------------------------------
   530                          ; tmsSpritePosXYReg: Set a sprite position from x/y registers
   531                          ; -----------------------------------------------------------------------------
   532                          !macro tmsSpritePosXYReg .ind {
   533                                  
   534                          
   535                                  ; sprite attr table
   536                                  +tmsSetAddrSpriteAttrTable .ind
   537                          
   538                                  tya
   539                                  +tmsPut 
   540                                  txa
   541                                  +tmsPut 
   542                          }
   543                          
   544                          
   545                          ; -----------------------------------------------------------------------------
   546                          ; tmsSetAddrSpriteColor: Change a sprite color
   547                          ; -----------------------------------------------------------------------------
   548                          !macro tmsSetAddrSpriteColor .ind {
   549                          
   550                                  ; sprite attr table
   551                                  +tmsSetAddressWrite TMS_VRAM_SPRITE_ATTR_ADDRESS + (.ind * 4) + 3
   552                          }
   553                          ; -----------------------------------------------------------------------------
   554                          ; tmsSpriteColor: Change a sprite color
   555                          ; -----------------------------------------------------------------------------
   556                          !macro tmsSpriteColor .ind, .color {
   557                          
   558                                  +tmsSetAddrSpriteColor .ind
   559                          
   560                                  +tmsPut .color
   561                          }
   562                          
   563                          
   564                          ; -----------------------------------------------------------------------------
   565                          ; tmsSetPosWrite: Set cursor position
   566                          ; -----------------------------------------------------------------------------
   567                          !macro tmsSetPosWrite .x, .y {
   568                                  +tmsSetAddressWrite (TMS_VRAM_NAME_ADDRESS + .y * 32 + .x)
   569                          }
   570                          
   571                          ; -----------------------------------------------------------------------------
   572                          ; tmsSetPosRead: Set read cursor position
   573                          ; -----------------------------------------------------------------------------
   574                          !macro tmsSetPosRead .x, .y {
   575                                  +tmsSetAddressRead (TMS_VRAM_NAME_ADDRESS + .y * 32 + .x)
   576                          }
   577                          
   578                          ; -----------------------------------------------------------------------------
   579                          ; tmsPrint: Print immediate text
   580                          ; -----------------------------------------------------------------------------
   581                          ; Inputs:
   582                          ;  str: String to print
   583                          ;  x: x position
   584                          ;  y: y position
   585                          ; -----------------------------------------------------------------------------
   586                          !macro tmsPrint .str, .x, .y {
   587                                  jmp .afterText
   588                          .textAddr
   589                                  !text .str,0
   590                          .afterText        
   591                          
   592                                  +tmsSetPosWrite .x, .y
   593                          
   594                                  lda #<.textAddr
   595                                  sta STR_ADDR_L
   596                                  lda #>.textAddr
   597                                  sta STR_ADDR_H
   598                                  jsr tmsPrint        
   599                          }
   600                          
   601                          
   602                          ; -----------------------------------------------------------------------------
   603                          ; tmsPrintCentre: Print centre-aligned immediate text
   604                          ; -----------------------------------------------------------------------------
   605                          ; Inputs:
   606                          ;  str: String to print
   607                          ;  y: y position
   608                          ; -----------------------------------------------------------------------------
   609                          !macro tmsPrintCentre .str, .y {
   610                                  jmp .afterText
   611                          .textAddr
   612                                  !text .str,0
   613                          .afterText        
   614                          
   615                                  +tmsSetPosWrite (32 - ((.afterText - 1) - .textAddr)) / 2, .y
   616                          
   617                                  lda #<.textAddr
   618                                  sta STR_ADDR_L
   619                                  lda #>.textAddr
   620                                  sta STR_ADDR_H
   621                                  jsr tmsPrint        
   622                          }
   623                          
   624                          
   625                          ; -----------------------------------------------------------------------------
   626                          ; tmsPrintZ: Print text
   627                          ; -----------------------------------------------------------------------------
   628                          ; Inputs:
   629                          ;  str: Address of zero-terminated string to print
   630                          ;  x: x position
   631                          ;  y: y position
   632                          ; -----------------------------------------------------------------------------
   633                          !macro tmsPrintZ .textAddr, .x, .y {
   634                                  +tmsSetPosWrite .x, .y
   635                          
   636                                  lda #<.textAddr
   637                                  sta STR_ADDR_L
   638                                  lda #>.textAddr
   639                                  sta STR_ADDR_H
   640                                  jsr tmsPrint        
   641                          }

; ******** Source: ../lib\gfx\tms9918.asm
    13                          
    14                          
    15                          TMS_FONT_DATA:

; ******** Source: ../lib\gfx\fonts\hbc56font.asm
     1                          ; 6502 - HBC-56 Font
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          
    10                          
    11                          
    12                          
    13                          
    14                          
    15                          
    16                          
    17                          
    18                          
    19                          
    20                          
    21                          
    22                          
    23                          
    24                          
    25                          
    26                          
    27                          
    28                          
    29                          
    30                          
    31                          
    32  e271 0000000000000000   !byte $00,$00,$00,$00,$00,$00,$00,$00 ; <SPACE>
    33  e279 1818181818001800   !byte $18,$18,$18,$18,$18,$00,$18,$00 ; !
    34  e281 6c6c6c0000000000   !byte $6C,$6C,$6C,$00,$00,$00,$00,$00 ; "
    35  e289 6c6cfe6cfe6c6c00   !byte $6C,$6C,$FE,$6C,$FE,$6C,$6C,$00 ; #
    36  e291 187ec07c06fc1800   !byte $18,$7E,$C0,$7C,$06,$FC,$18,$00 ; $
    37  e299 00c6cc183066c600   !byte $00,$C6,$CC,$18,$30,$66,$C6,$00 ; %
    38  e2a1 386c3876dccc7600   !byte $38,$6C,$38,$76,$DC,$CC,$76,$00 ; &
    39  e2a9 3030600000000000   !byte $30,$30,$60,$00,$00,$00,$00,$00 ; '
    40  e2b1 0c18303030180c00   !byte $0C,$18,$30,$30,$30,$18,$0C,$00 ; (
    41  e2b9 30180c0c0c183000   !byte $30,$18,$0C,$0C,$0C,$18,$30,$00 ; )
    42  e2c1 00663cff3c660000   !byte $00,$66,$3C,$FF,$3C,$66,$00,$00 ; *
    43  e2c9 0018187e18180000   !byte $00,$18,$18,$7E,$18,$18,$00,$00 ; +
    44  e2d1 0000000000181830   !byte $00,$00,$00,$00,$00,$18,$18,$30 ; ,
    45  e2d9 0000007e00000000   !byte $00,$00,$00,$7E,$00,$00,$00,$00 ; -
    46  e2e1 0000000000181800   !byte $00,$00,$00,$00,$00,$18,$18,$00 ; .
    47  e2e9 060c183060c08000   !byte $06,$0C,$18,$30,$60,$C0,$80,$00 ; /
    48  e2f1 7ccedef6e6c67c00   !byte $7C,$CE,$DE,$F6,$E6,$C6,$7C,$00 ; 0
    49  e2f9 1838181818187e00   !byte $18,$38,$18,$18,$18,$18,$7E,$00 ; 1
    50  e301 7cc6067cc0c0fe00   !byte $7C,$C6,$06,$7C,$C0,$C0,$FE,$00 ; 2
    51  e309 fc06063c0606fc00   !byte $FC,$06,$06,$3C,$06,$06,$FC,$00 ; 3
    52  e311 0cccccccfe0c0c00   !byte $0C,$CC,$CC,$CC,$FE,$0C,$0C,$00 ; 4
    53  e319 fec0fc0606c67c00   !byte $FE,$C0,$FC,$06,$06,$C6,$7C,$00 ; 5
    54  e321 7cc0c0fcc6c67c00   !byte $7C,$C0,$C0,$FC,$C6,$C6,$7C,$00 ; 6
    55  e329 fe06060c18303000   !byte $FE,$06,$06,$0C,$18,$30,$30,$00 ; 7
    56  e331 7cc6c67cc6c67c00   !byte $7C,$C6,$C6,$7C,$C6,$C6,$7C,$00 ; 8
    57  e339 7cc6c67e06067c00   !byte $7C,$C6,$C6,$7E,$06,$06,$7C,$00 ; 9
    58  e341 0018180000181800   !byte $00,$18,$18,$00,$00,$18,$18,$00 ; :
    59  e349 0018180000181830   !byte $00,$18,$18,$00,$00,$18,$18,$30 ; ;
    60  e351 0c18306030180c00   !byte $0C,$18,$30,$60,$30,$18,$0C,$00 ; <
    61  e359 00007e007e000000   !byte $00,$00,$7E,$00,$7E,$00,$00,$00 ; =
    62  e361 30180c060c183000   !byte $30,$18,$0C,$06,$0C,$18,$30,$00 ; >
    63  e369 3c660c1818001800   !byte $3C,$66,$0C,$18,$18,$00,$18,$00 ; ?
    64  e371 7cc6dededec07e00   !byte $7C,$C6,$DE,$DE,$DE,$C0,$7E,$00 ; @
    65  e379 386cc6c6fec6c600   !byte $38,$6C,$C6,$C6,$FE,$C6,$C6,$00 ; A
    66  e381 fcc6c6fcc6c6fc00   !byte $FC,$C6,$C6,$FC,$C6,$C6,$FC,$00 ; B
    67  e389 7cc6c0c0c0c67c00   !byte $7C,$C6,$C0,$C0,$C0,$C6,$7C,$00 ; C
    68  e391 f8ccc6c6c6ccf800   !byte $F8,$CC,$C6,$C6,$C6,$CC,$F8,$00 ; D
    69  e399 fec0c0f8c0c0fe00   !byte $FE,$C0,$C0,$F8,$C0,$C0,$FE,$00 ; E
    70  e3a1 fec0c0f8c0c0c000   !byte $FE,$C0,$C0,$F8,$C0,$C0,$C0,$00 ; F
    71  e3a9 7cc6c0c0cec67c00   !byte $7C,$C6,$C0,$C0,$CE,$C6,$7C,$00 ; G
    72  e3b1 c6c6c6fec6c6c600   !byte $C6,$C6,$C6,$FE,$C6,$C6,$C6,$00 ; H
    73  e3b9 7e18181818187e00   !byte $7E,$18,$18,$18,$18,$18,$7E,$00 ; I
    74  e3c1 0606060606c67c00   !byte $06,$06,$06,$06,$06,$C6,$7C,$00 ; J
    75  e3c9 c6ccd8f0d8ccc600   !byte $C6,$CC,$D8,$F0,$D8,$CC,$C6,$00 ; K
    76  e3d1 c0c0c0c0c0c0fe00   !byte $C0,$C0,$C0,$C0,$C0,$C0,$FE,$00 ; L
    77  e3d9 c6eefefed6c6c600   !byte $C6,$EE,$FE,$FE,$D6,$C6,$C6,$00 ; M
    78  e3e1 c6e6f6decec6c600   !byte $C6,$E6,$F6,$DE,$CE,$C6,$C6,$00 ; N
    79  e3e9 7cc6c6c6c6c67c00   !byte $7C,$C6,$C6,$C6,$C6,$C6,$7C,$00 ; O
    80  e3f1 fcc6c6fcc0c0c000   !byte $FC,$C6,$C6,$FC,$C0,$C0,$C0,$00 ; P
    81  e3f9 7cc6c6c6d6de7c06   !byte $7C,$C6,$C6,$C6,$D6,$DE,$7C,$06 ; Q
    82  e401 fcc6c6fcd8ccc600   !byte $FC,$C6,$C6,$FC,$D8,$CC,$C6,$00 ; R
    83  e409 7cc6c07c06c67c00   !byte $7C,$C6,$C0,$7C,$06,$C6,$7C,$00 ; S
    84  e411 ff18181818181800   !byte $FF,$18,$18,$18,$18,$18,$18,$00 ; T
    85  e419 c6c6c6c6c6c6fe00   !byte $C6,$C6,$C6,$C6,$C6,$C6,$FE,$00 ; U
    86  e421 c6c6c6c6c67c3800   !byte $C6,$C6,$C6,$C6,$C6,$7C,$38,$00 ; V
    87  e429 c6c6c6c6d6fe6c00   !byte $C6,$C6,$C6,$C6,$D6,$FE,$6C,$00 ; W
    88  e431 c6c66c386cc6c600   !byte $C6,$C6,$6C,$38,$6C,$C6,$C6,$00 ; X
    89  e439 c6c6c67c1830e000   !byte $C6,$C6,$C6,$7C,$18,$30,$E0,$00 ; Y
    90  e441 fe060c183060fe00   !byte $FE,$06,$0C,$18,$30,$60,$FE,$00 ; Z
    91  e449 3c30303030303c00   !byte $3C,$30,$30,$30,$30,$30,$3C,$00 ; [
    92  e451 c06030180c060200   !byte $C0,$60,$30,$18,$0C,$06,$02,$00 ; \
    93  e459 3c0c0c0c0c0c3c00   !byte $3C,$0C,$0C,$0C,$0C,$0C,$3C,$00 ; ]
    94  e461 10386cc600000000   !byte $10,$38,$6C,$C6,$00,$00,$00,$00 ; ^
    95  e469 00000000000000ff   !byte $00,$00,$00,$00,$00,$00,$00,$FF ; _
    96  e471 18180c0000000000   !byte $18,$18,$0C,$00,$00,$00,$00,$00 ; `
    97  e479 00007c067ec67e00   !byte $00,$00,$7C,$06,$7E,$C6,$7E,$00 ; a
    98  e481 c0c0c0fcc6c6fc00   !byte $C0,$C0,$C0,$FC,$C6,$C6,$FC,$00 ; b
    99  e489 00007cc6c0c67c00   !byte $00,$00,$7C,$C6,$C0,$C6,$7C,$00 ; c
   100  e491 0606067ec6c67e00   !byte $06,$06,$06,$7E,$C6,$C6,$7E,$00 ; d
   101  e499 00007cc6fec07c00   !byte $00,$00,$7C,$C6,$FE,$C0,$7C,$00 ; e
   102  e4a1 1c36307830307800   !byte $1C,$36,$30,$78,$30,$30,$78,$00 ; f
   103  e4a9 00007ec6c67e06fc   !byte $00,$00,$7E,$C6,$C6,$7E,$06,$FC ; g
   104  e4b1 c0c0fcc6c6c6c600   !byte $C0,$C0,$FC,$C6,$C6,$C6,$C6,$00 ; h
   105  e4b9 1800381818183c00   !byte $18,$00,$38,$18,$18,$18,$3C,$00 ; i
   106  e4c1 060006060606c67c   !byte $06,$00,$06,$06,$06,$06,$C6,$7C ; j
   107  e4c9 c0c0ccd8f8ccc600   !byte $C0,$C0,$CC,$D8,$F8,$CC,$C6,$00 ; k
   108  e4d1 3818181818183c00   !byte $38,$18,$18,$18,$18,$18,$3C,$00 ; l
   109  e4d9 0000ccfefed6d600   !byte $00,$00,$CC,$FE,$FE,$D6,$D6,$00 ; m
   110  e4e1 0000fcc6c6c6c600   !byte $00,$00,$FC,$C6,$C6,$C6,$C6,$00 ; n
   111  e4e9 00007cc6c6c67c00   !byte $00,$00,$7C,$C6,$C6,$C6,$7C,$00 ; o
   112  e4f1 0000fcc6c6fcc0c0   !byte $00,$00,$FC,$C6,$C6,$FC,$C0,$C0 ; p
   113  e4f9 00007ec6c67e0606   !byte $00,$00,$7E,$C6,$C6,$7E,$06,$06 ; q
   114  e501 0000fcc6c0c0c000   !byte $00,$00,$FC,$C6,$C0,$C0,$C0,$00 ; r
   115  e509 00007ec07c06fc00   !byte $00,$00,$7E,$C0,$7C,$06,$FC,$00 ; s
   116  e511 18187e1818180e00   !byte $18,$18,$7E,$18,$18,$18,$0E,$00 ; t
   117  e519 0000c6c6c6c67e00   !byte $00,$00,$C6,$C6,$C6,$C6,$7E,$00 ; u
   118  e521 0000c6c6c67c3800   !byte $00,$00,$C6,$C6,$C6,$7C,$38,$00 ; v
   119  e529 0000c6c6d6fe6c00   !byte $00,$00,$C6,$C6,$D6,$FE,$6C,$00 ; w
   120  e531 0000c66c386cc600   !byte $00,$00,$C6,$6C,$38,$6C,$C6,$00 ; x
   121  e539 0000c6c6c67e06fc   !byte $00,$00,$C6,$C6,$C6,$7E,$06,$FC ; y
   122  e541 0000fe0c3860fe00   !byte $00,$00,$FE,$0C,$38,$60,$FE,$00 ; z
   123  e549 0e18187018180e00   !byte $0E,$18,$18,$70,$18,$18,$0E,$00 ; {
   124  e551 1818180018181800   !byte $18,$18,$18,$00,$18,$18,$18,$00 ; |
   125  e559 7018180e18187000   !byte $70,$18,$18,$0E,$18,$18,$70,$00 ; }
   126  e561 76dc000000000000   !byte $76,$DC,$00,$00,$00,$00,$00,$00 ; ~

; ******** Source: ../lib\gfx\tms9918.asm
    16  e569 ffffffffffffffff   
    17                          
    18                          HAVE_TMS9918 = 1
    19                          
    20                          ; -------------------------
    21                          ; Constants
    22                          ; -------------------------
    23                          !ifndef TMS9918_IO_PORT { TMS9918_IO_PORT = $10
    24                                  !warn "TMS9918_IO_PORT not provided. Defaulting to ", TMS9918_IO_PORT
    25                          }
    26                          
    27                          !ifndef TMS9918_ZP_START { TMS9918_ZP_START = $30
    28                                  !warn "TMS9918_ZP_START not provided. Defaulting to ", TMS9918_ZP_START
    29                          }
    30                          
    31                          !ifndef TMS9918_RAM_START { TMS9918_RAM_START = $7ba0
    32                                  !warn "TMS9918_RAM_START not provided. Defaulting to ", TMS9918_RAM_START
    33                          }
    34                          
    35                          ; -----------------------------------------------------------------------------
    36                          ; Zero page
    37                          ; -----------------------------------------------------------------------------
    38                          TMS_TMP_ADDRESS         = TMS9918_ZP_START      ; 2 bytes
    39                          TMS9918_ZP_SIZE         = 2                     ; LAST ZP ADDRESS
    40                          
    41                          ; -----------------------------------------------------------------------------
    42                          ; High RAM
    43                          ; -----------------------------------------------------------------------------
    44                          .TMS9918_REG0_SHADOW_ADDR = TMS9918_RAM_START
    45                          .TMS9918_REG1_SHADOW_ADDR = TMS9918_RAM_START + 1
    46                          
    47                          TMS9918_CONSOLE_X         = TMS9918_RAM_START + 2
    48                          TMS9918_CONSOLE_Y         = TMS9918_RAM_START + 3
    49                          TMS9918_CONSOLE_SIZE_X    = TMS9918_RAM_START + 4
    50                          TMS9918_CONSOLE_LINE_LEN  = TMS9918_RAM_START + 5
    51                          .TMS9918_REGX             = TMS9918_RAM_START + 6
    52                          .TMS9918_REGY             = TMS9918_RAM_START + 7
    53                          .TMS9918_TMP_READ_ROW     = TMS9918_RAM_START + 8
    54                          .TMS9918_TMP_WRITE_ROW    = TMS9918_RAM_START + 9
    55                          
    56                          TMS9918_TMP_BUFFER        = TMS9918_RAM_START + 10 ; 40 bytes 
    57                          TMS9918_RAM_SIZE          = 50
    58                          
    59                          
    60                          
    61                          !if TMS9918_ZP_END < (TMS9918_ZP_START + TMS9918_ZP_SIZE) {
    62                                  !error "TMS9918_ZP requires ",TMS9918_ZP_SIZE," bytes. Allocated ",TMS9918_ZP_END - TMS9918_ZP_START
    63                          }
    64                          
    65                          !if TMS9918_RAM_END < (TMS9918_RAM_START + TMS9918_RAM_SIZE) {
    66                                  !error "TMS9918_RAM requires ",.TMS9918_RAM_SIZE," bytes. Allocated ",TMS9918_RAM_END - TMS9918_RAM_START
    67                          }
    68                          
    69                          
    70                          ; IO Ports
    71                          TMS9918_RAM     = IO_PORT_BASE_ADDRESS | TMS9918_IO_PORT
    72                          TMS9918_REG     = IO_PORT_BASE_ADDRESS | TMS9918_IO_PORT | $01
    73                          
    74                          
    75                          ; -----------------------------------------------------------------------------
    76                          ; VRAM addresses
    77                          ; -----------------------------------------------------------------------------
    78                          TMS_VRAM_NAME_ADDRESS           = $3800
    79                          TMS_VRAM_COLOR_ADDRESS          = $0000
    80                          TMS_VRAM_PATT_ADDRESS           = $2000
    81                          TMS_VRAM_SPRITE_ATTR_ADDRESS    = $3B00
    82                          TMS_VRAM_SPRITE_PATT_ADDRESS    = $1800
    83                          
    84                          ; -----------------------------------------------------------------------------
    85                          ; Register values
    86                          ; -----------------------------------------------------------------------------
    87                          TMS_R0_MODE_GRAPHICS_I          = $00
    88                          TMS_R0_MODE_GRAPHICS_II         = $02
    89                          TMS_R0_MODE_MULTICOLOR          = $00
    90                          TMS_R0_MODE_TEXT                = $00
    91                          TMS_R0_EXT_VDP_ENABLE           = $01
    92                          TMS_R0_EXT_VDP_DISABLE          = $00
    93                          
    94                          TMS_R1_RAM_16K                  = $80
    95                          TMS_R1_RAM_4K                   = $00
    96                          TMS_R1_DISP_BLANK               = $00
    97                          TMS_R1_DISP_ACTIVE              = $40
    98                          TMS_R1_INT_ENABLE               = $20
    99                          TMS_R1_INT_DISABLE              = $00
   100                          TMS_R1_MODE_GRAPHICS_I          = $00
   101                          TMS_R1_MODE_GRAPHICS_II         = $00
   102                          TMS_R1_MODE_MULTICOLOR          = $08
   103                          TMS_R1_MODE_TEXT                = $10
   104                          TMS_R1_SPRITE_8                 = $00
   105                          TMS_R1_SPRITE_16                = $02
   106                          TMS_R1_SPRITE_MAG1              = $00
   107                          TMS_R1_SPRITE_MAG2              = $01
   108                          
   109                          ; -----------------------------------------------------------------------------
   110                          ; Color palette
   111                          ; -----------------------------------------------------------------------------
   112                          TMS_TRANSPARENT         = $00
   113                          TMS_BLACK               = $01
   114                          TMS_MED_GREEN           = $02
   115                          TMS_LT_GREEN            = $03
   116                          TMS_DK_BLUE             = $04
   117                          TMS_LT_BLUE             = $05
   118                          TMS_DK_RED              = $06
   119                          TMS_CYAN                = $07
   120                          TMS_MED_RED             = $08
   121                          TMS_LT_RED              = $09
   122                          TMS_DK_YELLOW           = $0a
   123                          TMS_LT_YELLOW           = $0b
   124                          TMS_DK_GREEN            = $0c
   125                          TMS_MAGENTA             = $0d
   126                          TMS_GREY                = $0e
   127                          TMS_WHITE               = $0f
   128                          
   129                          TMS_GFX_TILE_WIDTH      = 8
   130                          TMS_GFX_TILE_HEIGHT     = 8
   131                          TMS_GFX_TILES_X         = 32
   132                          TMS_GFX_TILES_Y         = 24
   133                          TMS_GFX_PIXELS_X        = TMS_GFX_TILES_X * TMS_GFX_TILE_WIDTH
   134                          TMS_GFX_PIXELS_Y        = TMS_GFX_TILES_Y * TMS_GFX_TILE_HEIGHT
   135                          
   136                          TMS_TXT_TILE_WIDTH      = 6
   137                          TMS_TXT_TILE_HEIGHT     = 8
   138                          TMS_TXT_TILES_X         = 40
   139                          TMS_TXT_TILES_Y         = 24
   140                          TMS_TXT_PIXELS_X        = TMS_TXT_TILES_X * TMS_TXT_TILE_WIDTH
   141                          TMS_TXT_PIXELS_Y        = TMS_TXT_TILES_Y * TMS_TXT_TILE_HEIGHT
   142                          
   143                          TMS_SPRITE_SIZE         = 8
   144                          TMS_SPRITE_SIZE2X       = TMS_SPRITE_SIZE * 2
   145                          
   146                          !ifndef TMS_MODEL {
   147                                  !warn "Set TMS_MODEL to one of: 9918, 9929. Defaulting to 9918"
   148                                  TMS_MODEL = 9918
   149                          } 
   150                          
   151                          ; -------------------------
   152                          ; Constants
   153                          ; -------------------------
   154                          
   155                          !if TMS_MODEL = 9918 {
   156                                  TMS_FPS = 60
   157                          } else { !if TMS_MODEL = 9929 {
   158                                  TMS_FPS = 50
   159                          } else {
   160                                  !error "Unknown TMS_MODEL. Must be one of: 9918 or 9929"
   161                          }}
   162                          
   163                          ; -----------------------------------------------------------------------------
   164                          ; Default register values
   165                          ; -----------------------------------------------------------------------------
   166                          TMS_REGISTER_DATA:
   167  e571 00                 !byte TMS_R0_EXT_VDP_DISABLE
   168  e572 80                 !byte TMS_R1_RAM_16K
   169  e573 0e                 !byte TMS_VRAM_NAME_ADDRESS >> 10
   170  e574 00                 !byte TMS_VRAM_COLOR_ADDRESS >> 6
   171  e575 04                 !byte TMS_VRAM_PATT_ADDRESS >> 11
   172  e576 76                 !byte TMS_VRAM_SPRITE_ATTR_ADDRESS >> 7
   173  e577 03                 !byte TMS_VRAM_SPRITE_PATT_ADDRESS >> 11
   174  e578 11                 !byte TMS_BLACK << 4 | TMS_BLACK
   175                          
   176                          
   177                          ; -----------------------------------------------------------------------------
   178                          ; Delay subroutines required for TMS9918 CPU access windows
   179                          ; -----------------------------------------------------------------------------
   180                          ;      CONDITION          MODE    VDP DELAY       WAIT TIME          TOTAL TIME
   181                          ; -----------------------------------------------------------------------------
   182                          ;  Active Display Area   Text        2uS          0 - 1.1uS           2 - 3.1uS      
   183                          ;  Active Display Area   GFX I, II   2uS          0 - 5.95uS          2 - 8uS      
   184                          ;  4300uS after VSYNC    All         2uS             0uS                2uS      
   185                          ;  Reg 1 Blank Bit 0     All         2uS             0uS                2uS      
   186                          ;  Active Display Area   Multicolor  2uS          0 - 1.5uS           2 - 3.5uS      
   187                          ; -----------------------------------------------------------------------------
   188                          _tmsWaitData:
   189  e579 ea                         nop
   190  e57a ea                         nop
   191  e57b ea                         nop
   192  e57c ea                         nop
   193  e57d ea                         nop
   194  e57e ea                         nop
   195  e57f ea                         nop
   196  e580 ea                         nop
   197  e581 ea                         nop
   198                          _tmsWaitReg:
   199  e582 ea                         nop
   200  e583 ea                         nop
   201  e584 ea                         nop
   202  e585 60                         rts
   203                          
   204                          tmsSetAddressNextRow:
   205  e586 a524                       lda TMS_TMP_ADDRESS
   206  e588 18                         clc
   207  e589 6920                       adc #32
   208  e58b 8524                       sta TMS_TMP_ADDRESS
   209  e58d 9002                       bcc +
   210  e58f e625                       inc TMS_TMP_ADDRESS + 1
   211                          +
   212  e591 60                         rts
   213                          
   214                          ; -----------------------------------------------------------------------------
   215                          ; tmsSetAddressWrite: Set an address in the TMS9918 
   216                          ; -----------------------------------------------------------------------------
   217                          ; TMS_TMP_ADDRESS: Address to set
   218                          ; -----------------------------------------------------------------------------
   219                          tmsSetAddressWrite:
   220  e592 08                         php
   221  e593 78                         sei                     ; we can't be interrupted here
   222  e594 a524                       lda TMS_TMP_ADDRESS
   223  e596 8d117f                     sta TMS9918_REG
   224  e599 2082e5                     +tmsWaitReg
   225  e59c a525                       lda TMS_TMP_ADDRESS + 1
   226  e59e 0940                       ora #$40
   227  e5a0 8d117f                     sta TMS9918_REG
   228  e5a3 2082e5                     +tmsWaitReg
   229  e5a6 28                         plp
   230  e5a7 60                         rts
   231                          
   232                          ; -----------------------------------------------------------------------------
   233                          ; tmsSetAddressRead: Set an address to read from the TMS9918 
   234                          ; -----------------------------------------------------------------------------
   235                          ; TMS_TMP_ADDRESS: Address to read
   236                          ; -----------------------------------------------------------------------------
   237                          tmsSetAddressRead:
   238  e5a8 08                         php
   239  e5a9 78                         sei                     ; we can't be interrupted here
   240  e5aa a524                       lda TMS_TMP_ADDRESS
   241  e5ac 8d117f                     sta TMS9918_REG
   242  e5af 2082e5                     +tmsWaitReg
   243  e5b2 a525                       lda TMS_TMP_ADDRESS + 1
   244  e5b4 8d117f                     sta TMS9918_REG
   245  e5b7 2082e5                     +tmsWaitReg
   246  e5ba 28                         plp
   247  e5bb 60                         rts
   248                          
   249                          
   250                          ; -----------------------------------------------------------------------------
   251                          ; tmsSetRegister: Set a register value
   252                          ; -----------------------------------------------------------------------------
   253                          ; Inputs:
   254                          ;  A: The value to set
   255                          ;  X: The register (0 - 7)
   256                          ; -----------------------------------------------------------------------------
   257                          tmsSetRegister:
   258  e5bc 08                         php
   259  e5bd 78                         sei             ; we can't be interrupted here
   260  e5be 8d117f                     sta TMS9918_REG
   261  e5c1 2082e5                     +tmsWaitReg
   262  e5c4 8a                         txa
   263  e5c5 0980                       ora #$80
   264  e5c7 8d117f                     sta TMS9918_REG
   265  e5ca 2082e5                     +tmsWaitReg
   266  e5cd 28                         plp
   267  e5ce 60                         rts
   268                          
   269                          ; -----------------------------------------------------------------------------
   270                          ; tmsSetBackground: Set the background color (R7)
   271                          ; -----------------------------------------------------------------------------
   272                          ; Outputs:
   273                          ;  A: Color. High nibble = FG. Low nibble = BG
   274                          ; -----------------------------------------------------------------------------
   275                          tmsSetBackground:
   276  e5cf a207                       ldx #7
   277  e5d1 d0e9                       bne tmsSetRegister
   278                          
   279                          ; -----------------------------------------------------------------------------
   280                          ; tmsReg0Set: Set register 0
   281                          ; -----------------------------------------------------------------------------
   282                          ; Outputs:
   283                          ;  A: Field values to set (will be OR'd with existing Reg0)
   284                          ; -----------------------------------------------------------------------------
   285                          tmsReg0SetFields:
   286  e5d3 0d267b                     ora .TMS9918_REG0_SHADOW_ADDR
   287                          .tmsReg0SetFields:
   288  e5d6 8d267b                     sta .TMS9918_REG0_SHADOW_ADDR
   289  e5d9 a200                       ldx #0
   290  e5db f0df                       beq tmsSetRegister
   291                                  
   292                          ; -----------------------------------------------------------------------------
   293                          ; tmsReg0Clear: Clear register 0 
   294                          ; -----------------------------------------------------------------------------
   295                          ; Outputs:
   296                          ;  A: Field values to cleared (will be XOR'd with existing Reg0)
   297                          ; -----------------------------------------------------------------------------
   298                          tmsReg0ClearFields:
   299  e5dd 49ff                       eor #$ff
   300  e5df 2d267b                     and .TMS9918_REG0_SHADOW_ADDR
   301  e5e2 4cd6e5                     jmp .tmsReg0SetFields
   302                          
   303                          
   304                          ; -----------------------------------------------------------------------------
   305                          ; tmsReg1Set: Set register 0
   306                          ; -----------------------------------------------------------------------------
   307                          ; Outputs:
   308                          ;  A: Field values to set (will be OR'd with existing Reg1)
   309                          ; -----------------------------------------------------------------------------
   310                          tmsReg1SetFields:
   311  e5e5 0d277b                     ora .TMS9918_REG1_SHADOW_ADDR
   312                          .tmsReg1SetFields:
   313  e5e8 8d277b                     sta .TMS9918_REG1_SHADOW_ADDR
   314  e5eb a201                       ldx #1
   315  e5ed d0cd                       bne tmsSetRegister
   316                                  
   317                          ; -----------------------------------------------------------------------------
   318                          ; tmsReg1Clear: Clear register 1
   319                          ; -----------------------------------------------------------------------------
   320                          ; Outputs:
   321                          ;  A: Field values to cleared (will be XOR'd with existing Reg1)
   322                          ; -----------------------------------------------------------------------------
   323                          tmsReg1ClearFields:
   324  e5ef 49ff                       eor #$ff
   325  e5f1 2d277b                     and .TMS9918_REG1_SHADOW_ADDR
   326  e5f4 4ce8e5                     jmp .tmsReg1SetFields
   327                          
   328                          
   329                          ; -----------------------------------------------------------------------------
   330                          ; tmsModeReset: Reset graphics Mode
   331                          ; -----------------------------------------------------------------------------
   332                          tmsModeReset:
   333  e5f7 a903                       lda #$03
   334  e5f9 20dde5                     jsr tmsReg0ClearFields
   335                          
   336  e5fc a918                       lda #$18
   337  e5fe 20efe5                     jsr tmsReg1ClearFields
   338                          
   339                                  ; if we were in Graphics II, then we need to reset
   340                                  ; the color and pattern table addresses
   341  e601 a900                       lda #<(TMS_VRAM_COLOR_ADDRESS >> 6)
   342  e603 a203                       ldx #3
   343  e605 20bce5                     jsr tmsSetRegister
   344                          
   345  e608 a904                       lda #<(TMS_VRAM_PATT_ADDRESS >> 11)
   346  e60a a204                       ldx #4
   347  e60c 20bce5                     jsr tmsSetRegister
   348  e60f 60                         rts
   349                          
   350                          ; -----------------------------------------------------------------------------
   351                          ; tmsModeGraphicsI: Set up for Graphics I mode
   352                          ; -----------------------------------------------------------------------------
   353                          tmsModeGraphicsI:
   354  e610 20f7e5                     jsr tmsModeReset
   355                          
   356  e613 a900                       lda #TMS_R0_MODE_GRAPHICS_I
   357  e615 20d3e5                     jsr tmsReg0SetFields
   358                          
   359  e618 a900                       lda #TMS_R1_MODE_GRAPHICS_I
   360  e61a 20e5e5                     jsr tmsReg1SetFields
   361                          
   362  e61d a920                       lda #32
   363  e61f 8d2a7b                     sta TMS9918_CONSOLE_SIZE_X
   364  e622 60                         rts
   365                          
   366                          ; -----------------------------------------------------------------------------
   367                          ; tmsModeGraphicsII: Set up for Graphics II mode
   368                          ; -----------------------------------------------------------------------------
   369                          tmsModeGraphicsII:
   370  e623 20f7e5                     jsr tmsModeReset
   371                          
   372  e626 a902                       lda #TMS_R0_MODE_GRAPHICS_II
   373  e628 20d3e5                     jsr tmsReg0SetFields
   374                          
   375  e62b a900                       lda #TMS_R1_MODE_GRAPHICS_II
   376  e62d 20e5e5                     jsr tmsReg1SetFields
   377                          
   378                                  ; in Graphics II, Registers 3 and 4 work differently
   379                                  ;
   380                                  ; reg3 - Color table
   381                                  ;   $7f = $0000
   382                                  ;   $ff = $2000
   383                                  ;
   384                                  ; reg4 - Pattern table
   385                                  ;  $03 = $0000
   386                                  ;  $07 = $2000
   387                          
   388                                  ; set color table to $0000
   389  e630 a97f                       lda #$7f
   390  e632 a203                       ldx #3
   391  e634 20bce5                     jsr tmsSetRegister
   392                          
   393                                  ; set pattern table to $2000
   394  e637 a907                       lda #$07
   395  e639 a204                       ldx #4
   396  e63b 20bce5                     jsr tmsSetRegister
   397                          
   398  e63e a920                       lda #32
   399  e640 8d2a7b                     sta TMS9918_CONSOLE_SIZE_X
   400                          
   401  e643 60                         rts
   402                          
   403                          ; -----------------------------------------------------------------------------
   404                          ; tmsModeText: Set up for Text mode
   405                          ; -----------------------------------------------------------------------------
   406                          tmsModeText:
   407  e644 20f7e5                     jsr tmsModeReset
   408                          
   409  e647 a900                       lda #TMS_R0_MODE_TEXT
   410  e649 20d3e5                     jsr tmsReg0SetFields
   411                          
   412  e64c a910                       lda #TMS_R1_MODE_TEXT
   413  e64e 20e5e5                     jsr tmsReg1SetFields
   414                          
   415  e651 a928                       lda #40
   416  e653 8d2a7b                     sta TMS9918_CONSOLE_SIZE_X
   417                          
   418  e656 60                         rts
   419                          
   420                          ; -----------------------------------------------------------------------------
   421                          ; tmsModeMulticolor: Set up for Multicolor mode
   422                          ; -----------------------------------------------------------------------------
   423                          tmsModeMulticolor:
   424  e657 20f7e5                     jsr tmsModeReset
   425                          
   426  e65a a900                       lda #TMS_R0_MODE_MULTICOLOR
   427  e65c 20d3e5                     jsr tmsReg0SetFields
   428                          
   429  e65f a908                       lda #TMS_R1_MODE_MULTICOLOR
   430  e661 20e5e5                     jsr tmsReg1SetFields
   431  e664 60                         rts
   432                          
   433                          ; -----------------------------------------------------------------------------
   434                          ; tmsInit: Initialise the registers
   435                          ; -----------------------------------------------------------------------------
   436                          tmsInit:
   437  e665 08                         php
   438  e666 78                         sei                             ; we can't be interrupted here
   439  e667 ad71e5                     lda TMS_REGISTER_DATA
   440  e66a 8d267b                     sta .TMS9918_REG0_SHADOW_ADDR
   441  e66d ad72e5                     lda TMS_REGISTER_DATA + 1
   442  e670 8d277b                     sta .TMS9918_REG1_SHADOW_ADDR
   443                          
   444  e673 a900                       lda #0
   445  e675 8d287b                     sta TMS9918_CONSOLE_X
   446  e678 8d297b                     sta TMS9918_CONSOLE_Y
   447                          
   448                                  ; set up the registers
   449  e67b a200                       ldx #0
   450                          
   451                          @regLoop
   452  e67d bd71e5                             lda TMS_REGISTER_DATA, x
   453  e680 8d117f                             sta TMS9918_REG
   454  e683 2082e5                             +tmsWaitReg
   455  e686 8a                                 txa
   456  e687 0980                               ora #$80
   457  e689 8d117f                             sta TMS9918_REG
   458  e68c 2082e5                             +tmsWaitReg
   459  e68f e8                                 inx
   460  e690 e008                               cpx #8
   461  e692 d0e9                               bne @regLoop
   462                                  
   463  e694 2010e6                     jsr tmsModeGraphicsI
   464                          
   465                                  ; load all data into VRAM
   466  e697 20f9e6                     jsr tmsInitPattTable
   467                          
   468  e69a 2039e7                     jsr tmsInitTextTable
   469                                  
   470  e69d a917                       +tmsColorFgBg TMS_BLACK, TMS_CYAN
   471  e69f 2054e7                     jsr tmsInitEntireColorTable
   472                          
   473  e6a2 2075e7                     jsr tmsInitSpriteTable
   474                          
   475  e6a5 28                         plp
   476                                  
   477  e6a6 60                         rts
   478                          
   479                          ; -----------------------------------------------------------------------------
   480                          ; _tmsSendPage: Send A for a kilobyte
   481                          ; -----------------------------------------------------------------------------
   482                          _tmsSendKb
   483  e6a7 20b0e6                     jsr _tmsSendPage
   484  e6aa 20b0e6                     jsr _tmsSendPage
   485  e6ad 20b0e6                     jsr _tmsSendPage
   486                                  ; flow through
   487                                  
   488                          ; -----------------------------------------------------------------------------
   489                          ; _tmsSendPage: Send A for a whole page
   490                          ; -----------------------------------------------------------------------------
   491                          _tmsSendPage:
   492  e6b0 a220                       ldx #32
   493                          _tmsSendX8:
   494  e6b2 8d107f2079e5               +tmsPut
   495  e6b8 8d107f2079e5               +tmsPut
   496  e6be 8d107f2079e5               +tmsPut
   497  e6c4 8d107f2079e5               +tmsPut
   498  e6ca 8d107f2079e5               +tmsPut
   499  e6d0 8d107f2079e5               +tmsPut
   500  e6d6 8d107f2079e5               +tmsPut
   501  e6dc 8d107f2079e5               +tmsPut
   502  e6e2 ca                         dex
   503  e6e3 d0cd                       bne _tmsSendX8
   504  e6e5 60                         rts
   505                          
   506                          ; -----------------------------------------------------------------------------
   507                          ; _tmsSendEmptyPage: Send an empty page of data
   508                          ; -----------------------------------------------------------------------------
   509                          _tmsSendEmptyPage:
   510  e6e6 a900                       lda #0
   511  e6e8 f0c6                       beq _tmsSendPage ; rts in here
   512                          
   513                          ; -----------------------------------------------------------------------------
   514                          ; tmsSendBytes: Send bytes to the TMS (up to 1 page)
   515                          ; -----------------------------------------------------------------------------
   516                          ; Inputs:
   517                          ;   TMS_TMP_ADDRESS:    Holds source address
   518                          ;   X:                  Number of bytes (1 to 256)
   519                          ; -----------------------------------------------------------------------------
   520                          tmsSendBytes:
   521  e6ea a000                       ldy #0
   522                          -
   523  e6ec b124                       lda (TMS_TMP_ADDRESS), Y
   524  e6ee 8d107f2079e5               +tmsPut
   525  e6f4 c8                         iny
   526  e6f5 ca                         dex
   527  e6f6 d0f4                       bne -
   528  e6f8 60                         rts
   529                          
   530                          ; -----------------------------------------------------------------------------
   531                          ; tmsInitPattTable: Initialise the pattern table
   532                          ; -----------------------------------------------------------------------------
   533                          tmsInitPattTable:
   534                                  
   535                          
   536                                  ; pattern table
   537  e6f9 0878a9008d117f20...        +tmsSetAddrPattTable
   538                          
   539                                  ; (0 - 31) all empty
   540  e70c 20e6e6                     jsr _tmsSendEmptyPage
   541                          
   542  e70f a9718524a9e28525...        +tmsSendData TMS_FONT_DATA, $300
   543                          
   544                                  ; (128 - 159) all empty
   545  e72c 20e6e6                     jsr _tmsSendEmptyPage
   546                          
   547                                  ; (160 - 191) all empty
   548  e72f 20e6e6                     jsr _tmsSendEmptyPage
   549                          
   550                                  ; (192 - 223) all empty
   551  e732 20e6e6                     jsr _tmsSendEmptyPage
   552                          
   553                                  ; (224 - 255) all empty
   554  e735 20e6e6                     jsr _tmsSendEmptyPage
   555                          
   556                                  
   557                          
   558  e738 60                         rts
   559                          
   560                          ; -----------------------------------------------------------------------------
   561                          ; tmsInitTextTable: Initialise the text (tilemap) table
   562                          ; -----------------------------------------------------------------------------
   563                          tmsInitTextTable:
   564                                  
   565                          
   566                                  ; text table table
   567  e739 0878a9008d117f20...        +tmsSetAddrNameTable
   568                          
   569                          
   570  e74c a900                       lda #0
   571  e74e a27e                       ldx #(42 * 3)
   572  e750 20b2e6                     jsr _tmsSendX8
   573                          
   574  e753 60                         rts
   575                          
   576                          
   577                          ; -----------------------------------------------------------------------------
   578                          ; tmsInitEntireColorTable: Initialise the full color table
   579                          ; -----------------------------------------------------------------------------
   580                          ; Inputs:
   581                          ;   A: Color (fg/bg) to initialise
   582                          
   583                          tmsInitEntireColorTable:
   584  e754 a220                       ldx #32
   585                          
   586                          ; tmsInitColorTable: Initialise the color table
   587                          
   588                          ; Inputs:
   589                          ;   A: Color (fg/bg) to initialise
   590                          ;   X: Number of elements to initialise (1 to 32)
   591                          ; -----------------------------------------------------------------------------
   592                          tmsInitColorTable:
   593                                  
   594  e756 48                         pha
   595                          
   596                                  ; color table
   597  e757 0878a9008d117f20...        +tmsSetAddrColorTable
   598                          
   599  e76a 68                         pla
   600                          -
   601  e76b 8d107f2079e5               +tmsPut
   602  e771 ca                         dex
   603  e772 d0f7                       bne -
   604                          
   605  e774 60                         rts
   606                          
   607                          ; -----------------------------------------------------------------------------
   608                          ; tmsInitSpriteTable: Initialise the sprite table
   609                          ; -----------------------------------------------------------------------------
   610                          tmsInitSpriteTable:
   611                                  
   612                          
   613                                  ; sprites table
   614  e775 0878a9008d117f20...        +tmsSetAddrSpriteAttrTable
   615                          
   616  e788 a220                       ldx #32
   617                          -
   618                                  ; Vertical position
   619  e78a a9d08d107f2079e5           +tmsPut $D0        ; 208 ($D0) stops processing of sprites
   620  e792 a9008d107f2079e5           +tmsPut $00        ; Horizontal position
   621                          
   622                                  ; Index (A still 0)
   623  e79a 8d107f2079e5               +tmsPut
   624                                  ; Early Clock / Color  (A still 0)
   625  e7a0 8d107f2079e5               +tmsPut
   626  e7a6 ca                         dex
   627  e7a7 d0e1                       bne -
   628                          
   629                                  
   630                          
   631  e7a9 60                         rts
   632                          
   633                          ; -----------------------------------------------------------------------------
   634                          ; tmsTileXyAtPixelXy: Return tile position at pixel position
   635                          ; -----------------------------------------------------------------------------
   636                          ; Inputs:
   637                          ;  X: Pixel position X
   638                          ;  Y: Pixel position Y
   639                          ; Outputs:
   640                          ;  X: Tile position X
   641                          ;  Y: Tile position Y
   642                          ; -----------------------------------------------------------------------------
   643                          tmsTileXyAtPixelXy:
   644  e7aa 48                         pha
   645  e7ab 8a                         txa
   646  e7ac 4a4a4a                     +div8
   647  e7af aa                         tax
   648                          
   649  e7b0 98                         tya
   650  e7b1 4a4a4a                     +div8
   651  e7b4 a8                         tay
   652  e7b5 68                         pla
   653  e7b6 60                         rts
   654                          
   655                          ; -----------------------------------------------------------------------------
   656                          ; tmsHex8: Output an 8-bit byte as hexadecimal
   657                          ; -----------------------------------------------------------------------------
   658                          ; Inputs:
   659                          ;  A: The value to output
   660                          ; -----------------------------------------------------------------------------
   661                          tmsHex8:
   662  e7b7 48                         pha
   663  e7b8 4a4a4a4a                   +lsr4
   664  e7bc aa                         tax
   665  e7bd bdd4e7                     lda .H2, x
   666  e7c0 8d107f2079e5               +tmsPut 
   667  e7c6 68                         pla
   668  e7c7 290f                       and #$0f
   669  e7c9 aa                         tax
   670  e7ca bdd4e7                     lda .H2, x
   671  e7cd 8d107f2079e5               +tmsPut 
   672                                  
   673  e7d3 60                         rts
   674                          
   675  e7d4 3031323334353637....H2 !text "0123456789abcdef"
   676                          
   677                          
   678                          ; -----------------------------------------------------------------------------
   679                          ; tmsSetSpriteTmpAddress: Set TMS_TMP_ADDRESS for a given sprite attributes
   680                          ; -----------------------------------------------------------------------------
   681                          ; Inputs:
   682                          ;   A: sprite index (0-31)
   683                          ; -----------------------------------------------------------------------------
   684                          tmsSetSpriteTmpAddress:
   685  e7e4 0a                         asl
   686  e7e5 0a                         asl
   687  e7e6 8524                       sta TMS_TMP_ADDRESS
   688                          
   689  e7e8 a93b                       lda #>TMS_VRAM_SPRITE_ATTR_ADDRESS
   690  e7ea 8525                       sta TMS_TMP_ADDRESS + 1
   691  e7ec 60                         rts
   692                          
   693                          ; -----------------------------------------------------------------------------
   694                          ; tmsSetPosTmpAddress: Set TMS_TMP_ADDRESS for a given text position
   695                          ; -----------------------------------------------------------------------------
   696                          ; Inputs:
   697                          ;   X: X position (0 - 31)
   698                          ;   Y: Y position (0 - 23)
   699                          ; -----------------------------------------------------------------------------
   700                          tmsSetPosTmpAddress:
   701  e7ed a938                       lda #>TMS_VRAM_NAME_ADDRESS
   702  e7ef 8525                       sta TMS_TMP_ADDRESS + 1
   703                                  
   704                                  ; this can be better. rotate and save, perhaps
   705                          
   706  e7f1 98                         tya
   707  e7f2 4a4a4a                     +div8
   708  e7f5 18                         clc
   709  e7f6 6525                       adc TMS_TMP_ADDRESS + 1
   710  e7f8 8525                       sta TMS_TMP_ADDRESS + 1
   711  e7fa 98                         tya
   712  e7fb 2907                       and #$07
   713  e7fd 0a0a0a0a0a                 +mul32
   714  e802 8524                       sta TMS_TMP_ADDRESS
   715  e804 8a                         txa
   716  e805 0524                       ora TMS_TMP_ADDRESS
   717  e807 8524                       sta TMS_TMP_ADDRESS
   718  e809 60                         rts
   719                          
   720                          ; -----------------------------------------------------------------------------
   721                          ; tmsSetPosTmpAddressText: Set TMS_TMP_ADDRESS for a given text position
   722                          ; -----------------------------------------------------------------------------
   723                          ; Inputs:
   724                          ;   X: X position (0 - 39)
   725                          ;   Y: Y position (0 - 23)
   726                          ; -----------------------------------------------------------------------------
   727                          tmsSetPosTmpAddressText:
   728  e80a a938                       lda #>TMS_VRAM_NAME_ADDRESS
   729  e80c 8525                       sta TMS_TMP_ADDRESS + 1
   730  e80e a900                       lda #<TMS_VRAM_NAME_ADDRESS
   731  e810 8524                       sta TMS_TMP_ADDRESS
   732                          
   733                          .tmsSetPosTmpAddressTextLoop
   734  e812 c000                       cpy #0
   735  e814 f00e                       beq ++
   736  e816 18                         clc
   737  e817 a524                       lda TMS_TMP_ADDRESS
   738  e819 6928                       adc #40
   739  e81b 8524                       sta TMS_TMP_ADDRESS
   740  e81d 9002                       bcc +
   741  e81f e625                       inc TMS_TMP_ADDRESS + 1
   742                          +
   743  e821 88                         dey
   744  e822 d0ee                       bne .tmsSetPosTmpAddressTextLoop
   745                          ++
   746  e824 18                         clc
   747  e825 8a                         txa
   748  e826 6524                       adc TMS_TMP_ADDRESS
   749  e828 8524                       sta TMS_TMP_ADDRESS
   750  e82a 9002                       bcc +
   751  e82c e625                       inc TMS_TMP_ADDRESS + 1
   752                          +
   753  e82e 60                         rts
   754                          
   755                          
   756                          tmsConsoleScrollLine:
   757  e82f a900                       lda #0
   758  e831 8d2f7b                     sta .TMS9918_TMP_WRITE_ROW
   759  e834 a901                       lda #1
   760  e836 8d2e7b                     sta .TMS9918_TMP_READ_ROW
   761                          .nextRow:
   762                          
   763  e839 ac2e7b                     ldy .TMS9918_TMP_READ_ROW
   764  e83c a200                       ldx #0
   765  e83e a928                       lda #40
   766  e840 cd2a7b                     cmp TMS9918_CONSOLE_SIZE_X
   767  e843 f006                       beq +
   768  e845 20ede7                     jsr tmsSetPosTmpAddress
   769  e848 4c4ee8                     jmp ++
   770                          +
   771  e84b 200ae8                     jsr tmsSetPosTmpAddressText
   772                          ++
   773  e84e 20a8e5                     jsr tmsSetAddressRead
   774                          
   775  e851 207fe8                     jsr .tmsBufferIn
   776                          
   777  e854 a200                       ldx #0
   778  e856 ac2f7b                     ldy .TMS9918_TMP_WRITE_ROW
   779  e859 a200                       ldx #0
   780  e85b a928                       lda #40
   781  e85d cd2a7b                     cmp TMS9918_CONSOLE_SIZE_X
   782  e860 f006                       beq +
   783  e862 20ede7                     jsr tmsSetPosTmpAddress
   784  e865 4c6be8                     jmp ++
   785                          +
   786  e868 200ae8                     jsr tmsSetPosTmpAddressText
   787                          ++
   788  e86b 2092e5                     jsr tmsSetAddressWrite
   789                          
   790  e86e 2091e8                     jsr .tmsBufferOut
   791                          
   792                          
   793  e871 ee2f7b                     inc .TMS9918_TMP_WRITE_ROW
   794  e874 ee2e7b                     inc .TMS9918_TMP_READ_ROW
   795                          
   796  e877 ad2e7b                     lda .TMS9918_TMP_READ_ROW
   797  e87a c919                       cmp #25
   798                          
   799  e87c d0bb                       bne .nextRow
   800                          
   801                          
   802                                  ; copy to buffer 32 bytes at a time, write back  24 rows for gfx, 30 "rows" for text
   803  e87e 60                         rts
   804                          
   805                          .tmsBufferIn:
   806  e87f a200                       ldx #0
   807                          -
   808  e881 ad107f2079e5               +tmsGet
   809  e887 9d307b                     sta TMS9918_TMP_BUFFER, x
   810  e88a e8                         inx
   811  e88b ec2a7b                     cpx TMS9918_CONSOLE_SIZE_X
   812  e88e d0f1                       bne -
   813  e890 60                         rts
   814                          
   815                          .tmsBufferOut:
   816  e891 a200                       ldx #0
   817                          
   818                          -
   819  e893 bd307b                     lda TMS9918_TMP_BUFFER, x
   820  e896 8d107f2079e5               +tmsPut
   821  e89c e8                         inx
   822  e89d ec2a7b                     cpx TMS9918_CONSOLE_SIZE_X
   823  e8a0 d0f1                       bne -
   824  e8a2 60                         rts
   825                          
   826                          ; -----------------------------------------------------------------------------
   827                          ; tmsIncPosConsole: Increment console position
   828                          ; -----------------------------------------------------------------------------
   829                          tmsIncPosConsole:
   830  e8a3 ee287b                     inc TMS9918_CONSOLE_X
   831  e8a6 ad287b                     lda TMS9918_CONSOLE_X
   832  e8a9 cd2a7b                     cmp TMS9918_CONSOLE_SIZE_X
   833  e8ac d008                       bne +
   834  e8ae a900                       lda #0
   835  e8b0 8d287b                     sta TMS9918_CONSOLE_X
   836  e8b3 ee297b                     inc TMS9918_CONSOLE_Y
   837                          +
   838  e8b6 ad297b                     lda TMS9918_CONSOLE_Y
   839  e8b9 c918                       cmp #24
   840  e8bb 9006                       bcc +
   841  e8bd ce297b                     dec TMS9918_CONSOLE_Y
   842  e8c0 4c2fe8                     jmp tmsConsoleScrollLine
   843                          +
   844  e8c3 60                         rts
   845                          
   846                          
   847                          ; -----------------------------------------------------------------------------
   848                          ; tmsDecPosConsole: Increment console position
   849                          ; -----------------------------------------------------------------------------
   850                          tmsDecPosConsole:
   851  e8c4 ce287b                     dec TMS9918_CONSOLE_X
   852  e8c7 1017                       bpl ++
   853  e8c9 ad2a7b                     lda TMS9918_CONSOLE_SIZE_X
   854  e8cc 8d287b                     sta TMS9918_CONSOLE_X
   855  e8cf ce287b                     dec TMS9918_CONSOLE_X
   856  e8d2 a900                       lda #0
   857  e8d4 cd297b                     cmp TMS9918_CONSOLE_Y
   858  e8d7 d004                       bne +
   859  e8d9 8d287b                     sta TMS9918_CONSOLE_X
   860  e8dc 60                         rts        
   861                          +
   862  e8dd ce297b                     dec TMS9918_CONSOLE_Y
   863                          ++
   864  e8e0 60                         rts
   865                          
   866                          
   867                          ; -----------------------------------------------------------------------------
   868                          ; tmsConsoleHome: Set cursor position top left
   869                          ; -----------------------------------------------------------------------------
   870                          tmsConsoleHome:
   871  e8e1 9c287b                     stz TMS9918_CONSOLE_X
   872  e8e4 9c297b                     stz TMS9918_CONSOLE_Y
   873                          
   874                                  ; flow through
   875                          
   876                          ; -----------------------------------------------------------------------------
   877                          ; tmsSetPosConsole: Set cursor position to console position
   878                          ; -----------------------------------------------------------------------------
   879                          tmsSetPosConsole:
   880  e8e7 ae287b                     ldx TMS9918_CONSOLE_X
   881  e8ea ac297b                     ldy TMS9918_CONSOLE_Y
   882                          
   883                                  ; flow through
   884                          
   885                          ; -----------------------------------------------------------------------------
   886                          ; tmsSetPosWrite: Set cursor position
   887                          ; -----------------------------------------------------------------------------
   888                          ; Inputs:
   889                          ;   X: X position (0 - 31)
   890                          ;   Y: Y position (0 - 23)
   891                          ; -----------------------------------------------------------------------------
   892                          tmsSetPosWrite:
   893  e8ed a910                       lda #TMS_R1_MODE_TEXT
   894  e8ef 2c277b                     bit .TMS9918_REG1_SHADOW_ADDR
   895  e8f2 d006                       bne tmsSetPosWriteText
   896  e8f4 20ede7                     jsr tmsSetPosTmpAddress
   897  e8f7 4c92e5                     jmp tmsSetAddressWrite
   898                          
   899                          ; -----------------------------------------------------------------------------
   900                          ; tmsSetPosWrite: Set cursor position (text mode)
   901                          ; -----------------------------------------------------------------------------
   902                          ; Inputs:
   903                          ;   X: X position (0 - 39)
   904                          ;   Y: Y position (0 - 23)
   905                          ; -----------------------------------------------------------------------------
   906                          tmsSetPosWriteText:
   907  e8fa 200ae8                     jsr tmsSetPosTmpAddressText
   908  e8fd 4c92e5                     jmp tmsSetAddressWrite
   909                          
   910                          ; -----------------------------------------------------------------------------
   911                          ; tmsSetPosRead: Set cursor position to read from
   912                          ; -----------------------------------------------------------------------------
   913                          ; Inputs:
   914                          ;   X: X position (0 - 31)
   915                          ;   Y: Y position (0 - 23)
   916                          ; -----------------------------------------------------------------------------
   917                          tmsSetPosRead:
   918  e900 20ede7                     jsr tmsSetPosTmpAddress
   919  e903 4ca8e5                     jmp tmsSetAddressRead
   920                          ; -----------------------------------------------------------------------------
   921                          ; tmsSetColorTmpAddressII: Set TMS_TMP_ADDRESS for a given mode II color definition
   922                          ; -----------------------------------------------------------------------------
   923                          ; Inputs:
   924                          ;   X: X position
   925                          ;   Y: Y position
   926                          ; -----------------------------------------------------------------------------
   927                          tmsSetColorTmpAddressII:
   928  e906 a900                       lda #>TMS_VRAM_COLOR_ADDRESS
   929  e908 8002                       bra .addXYToAddress
   930                          
   931                          ; -----------------------------------------------------------------------------
   932                          ; tmsSetPatternTmpAddress: Set TMS_TMP_ADDRESS for a given mode II pattern definition
   933                          ; -----------------------------------------------------------------------------
   934                          ; Inputs:
   935                          ;   X: X position
   936                          ;   Y: Y position
   937                          ; -----------------------------------------------------------------------------
   938                          tmsSetPatternTmpAddressII:
   939  e90a a920                       lda #>TMS_VRAM_PATT_ADDRESS
   940                          
   941                          .addXYToAddress:
   942  e90c 8525                       sta TMS_TMP_ADDRESS + 1
   943                          
   944  e90e 98                         tya
   945  e90f 4a4a4a                     +lsr3
   946  e912 0525                       ora TMS_TMP_ADDRESS + 1
   947  e914 8525                       sta TMS_TMP_ADDRESS + 1
   948                          
   949  e916 8a                         txa
   950  e917 29f8                       and #$f8
   951  e919 8524                       sta TMS_TMP_ADDRESS
   952                          
   953  e91b 98                         tya
   954  e91c 2907                       and #$07
   955  e91e 0524                       ora TMS_TMP_ADDRESS
   956  e920 8524                       sta TMS_TMP_ADDRESS
   957                          
   958  e922 60                         rts
   959                          
   960                          ; -----------------------------------------------------------------------------
   961                          ; tmsSetPatternTmpAddress: Set TMS_TMP_ADDRESS for a given pattern definition
   962                          ; -----------------------------------------------------------------------------
   963                          ; Inputs:
   964                          ;   A: Pattern number
   965                          ;   Y: Y offset (row) in the pattern
   966                          ; -----------------------------------------------------------------------------
   967                          tmsSetPatternTmpAddressBank0:
   968                          tmsSetPatternTmpAddress:
   969  e923 48                         pha
   970  e924 a920                       lda #>TMS_VRAM_PATT_ADDRESS
   971  e926 8525                       sta TMS_TMP_ADDRESS + 1
   972                                  
   973  e928 68                         pla
   974  e929 48                         pha
   975                          
   976  e92a 4a4a4a4a4a                 +div32
   977  e92f 18                         clc
   978  e930 6525                       adc TMS_TMP_ADDRESS + 1
   979  e932 8525                       sta TMS_TMP_ADDRESS + 1
   980  e934 68                         pla
   981  e935 0a0a0a                     +mul8
   982  e938 8524                       sta TMS_TMP_ADDRESS
   983  e93a 98                         tya
   984  e93b 0524                       ora TMS_TMP_ADDRESS
   985  e93d 8524                       sta TMS_TMP_ADDRESS
   986  e93f 60                         rts
   987                          
   988                          ; -----------------------------------------------------------------------------
   989                          ; tmsSetPatternTmpAddressBank1: Set TMS_TMP_ADDRESS for a given pattern 
   990                          ;                               definition in bank 1 (GFX II)
   991                          ; -----------------------------------------------------------------------------
   992                          ; Inputs:
   993                          ;   A: Pattern number
   994                          ;   Y: Y offset (row) in the pattern
   995                          ; -----------------------------------------------------------------------------
   996                          tmsSetPatternTmpAddressBank1:
   997  e940 2023e9                     jsr tmsSetPatternTmpAddress
   998  e943 a525                       lda TMS_TMP_ADDRESS + 1
   999  e945 18                         clc
  1000  e946 6908                       adc #8
  1001  e948 8525                       sta TMS_TMP_ADDRESS + 1
  1002  e94a 60                         rts
  1003                          
  1004                          ; -----------------------------------------------------------------------------
  1005                          ; tmsSetPatternTmpAddressBank2: Set TMS_TMP_ADDRESS for a given pattern 
  1006                          ;                               definition in bank 2 (GFX II)
  1007                          ; -----------------------------------------------------------------------------
  1008                          ; Inputs:
  1009                          ;   A: Pattern number
  1010                          ;   Y: Y offset (row) in the pattern
  1011                          ; -----------------------------------------------------------------------------
  1012                          tmsSetPatternTmpAddressBank2:
  1013  e94b 2023e9                     jsr tmsSetPatternTmpAddress
  1014  e94e a525                       lda TMS_TMP_ADDRESS + 1
  1015  e950 18                         clc
  1016  e951 6910                       adc #16
  1017  e953 8525                       sta TMS_TMP_ADDRESS + 1
  1018  e955 60                         rts        
  1019                          
  1020                          ; -----------------------------------------------------------------------------
  1021                          ; tmsSetPatternWrite: Set pattern definition to write to
  1022                          ; -----------------------------------------------------------------------------
  1023                          ; Inputs:
  1024                          ;   A: Pattern number
  1025                          ;   Y: Y offset (row) in the pattern
  1026                          ; -----------------------------------------------------------------------------
  1027                          tmsSetPatternWrite:
  1028  e956 2023e9                     jsr tmsSetPatternTmpAddress
  1029  e959 4c92e5                     jmp tmsSetAddressWrite
  1030                          
  1031                          ; -----------------------------------------------------------------------------
  1032                          ; tmsSetPatternRead: Set pattern definition to read from
  1033                          ; -----------------------------------------------------------------------------
  1034                          ; Inputs:
  1035                          ;   A: Pattern number
  1036                          ;   Y: Y offset (row) in the pattern
  1037                          ; -----------------------------------------------------------------------------
  1038                          tmsSetPatternRead:
  1039  e95c 2023e9                     jsr tmsSetPatternTmpAddress
  1040  e95f 4ca8e5                     jmp tmsSetAddressRead
  1041                          
  1042                          
  1043                          ; -----------------------------------------------------------------------------
  1044                          ; tmsPrint: Print a null-terminated string
  1045                          ; -----------------------------------------------------------------------------
  1046                          ; Inputs:
  1047                          ;  STR_ADDR: Contains address of null-terminated string
  1048                          ; Prerequisites:
  1049                          ;  TMS address already set using +tmsSetAddressWrite
  1050                          ; -----------------------------------------------------------------------------
  1051                          tmsPrint:
  1052  e962 a000                       ldy #0
  1053                          -
  1054  e964 2079e5                     +tmsWaitData
  1055  e967 b134                       lda (STR_ADDR), y
  1056  e969 f009                       beq +
  1057  e96b 8d107f2079e5               +tmsPut 
  1058  e971 c8                         iny
  1059  e972 d0f0                       bne -
  1060                          +
  1061  e974 60                         rts
  1062                          
  1063                          
  1064                          ; -----------------------------------------------------------------------------
  1065                          ; tmsConsoleOut: Print a null-terminated string
  1066                          ; -----------------------------------------------------------------------------
  1067                          ; Inputs:
  1068                          ;  'A': Character to output to console
  1069                          ; -----------------------------------------------------------------------------
  1070                          tmsConsoleOut:
  1071  e975 8e2c7b                     stx .TMS9918_REGX
  1072  e978 8c2d7b                     sty .TMS9918_REGY
  1073  e97b 08                         php
  1074  e97c 78                         sei
  1075  e97d c90d                       cmp #$0d ; enter
  1076  e97f f021                       beq .tmsConsoleNewline
  1077  e981 c90a                       cmp #$0a ; enter
  1078  e983 f01d                       beq .tmsConsoleNewline
  1079                          
  1080  e985 c908                       cmp #$08 ; backspace
  1081  e987 f01e                       beq .tmsConsoleBackspace
  1082                          
  1083  e989 48                         pha
  1084  e98a 20e7e8                     jsr tmsSetPosConsole
  1085  e98d 68                         pla
  1086  e98e 8d107f2079e5               +tmsPut
  1087  e994 20a3e8                     jsr tmsIncPosConsole
  1088  e997 ee2b7b                     inc TMS9918_CONSOLE_LINE_LEN
  1089                          
  1090                          .endConsoleOut
  1091  e99a 28                         plp
  1092  e99b ac2d7b                     ldy .TMS9918_REGY
  1093  e99e ae2c7b                     ldx .TMS9918_REGX
  1094  e9a1 60                         rts
  1095                          
  1096                          .tmsConsoleNewline
  1097  e9a2 20bce9                     jsr tmsConsoleNewline
  1098  e9a5 80f3                       bra .endConsoleOut
  1099                          
  1100                          .tmsConsoleBackspace
  1101  e9a7 20e3e9                     jsr tmsConsoleBackspace
  1102  e9aa 80ee                       bra .endConsoleOut
  1103                          
  1104                          
  1105                          ; -----------------------------------------------------------------------------
  1106                          ; tmsConsolePrint: Print a null-terminated string (console mode)
  1107                          ; -----------------------------------------------------------------------------
  1108                          ; Inputs:
  1109                          ;  STR_ADDR: Contains address of null-terminated string
  1110                          ; Prerequisites:
  1111                          ;  TMS address already set using +tmsSetAddressWrite
  1112                          ; -----------------------------------------------------------------------------
  1113                          tmsConsolePrint:
  1114  e9ac a000                       ldy #0
  1115                          -
  1116  e9ae 2079e5                     +tmsWaitData
  1117  e9b1 b134                       lda (STR_ADDR), y
  1118  e9b3 f006                       beq +
  1119  e9b5 2075e9                     jsr tmsConsoleOut
  1120  e9b8 c8                         iny
  1121  e9b9 d0f3                       bne -
  1122                          +
  1123  e9bb 60                         rts
  1124                          
  1125                          ; -----------------------------------------------------------------------------
  1126                          ; tmsConsoleNewline: Output a newline to the console (scrolls if on last line)
  1127                          ; -----------------------------------------------------------------------------
  1128                          tmsConsoleNewline:
  1129  e9bc 20e7e8                     jsr tmsSetPosConsole
  1130  e9bf a9208d107f2079e5           +tmsPut ' '
  1131  e9c7 ad287b                     lda TMS9918_CONSOLE_X
  1132  e9ca d008                       bne +
  1133  e9cc ad2b7b                     lda TMS9918_CONSOLE_LINE_LEN
  1134  e9cf f003                       beq +
  1135  e9d1 60                         rts
  1136  e9d2 f000                       beq +
  1137                          +
  1138  e9d4 ad2a7b                     lda TMS9918_CONSOLE_SIZE_X
  1139  e9d7 8d287b                     sta TMS9918_CONSOLE_X
  1140  e9da ce287b                     dec TMS9918_CONSOLE_X
  1141  e9dd 9c2b7b                     stz TMS9918_CONSOLE_LINE_LEN
  1142  e9e0 4ca3e8                     jmp tmsIncPosConsole
  1143                          
  1144                          
  1145                          ; -----------------------------------------------------------------------------
  1146                          ; tmsConsoleBackspace: Output a backspace to the console
  1147                          ; -----------------------------------------------------------------------------
  1148                          tmsConsoleBackspace:
  1149  e9e3 20c4e8                     jsr tmsDecPosConsole
  1150  e9e6 a9202075e9                 +tmsConsoleOut ' '
  1151  e9eb a9208d107f2079e5           +tmsPut ' '
  1152  e9f3 ce2b7b                     dec TMS9918_CONSOLE_LINE_LEN
  1153  e9f6 4cc4e8                     jmp tmsDecPosConsole

; ******** Source: kernel.asm
   158                          
   159                          }
   160                          
   161                          !ifndef HBC56_DISABLE_SFXMAN {
   162                                  !src "sfx/sfxman.asm"
   163                          }
   164                          
   165                          !ifndef HBC56_DISABLE_LCD {
   166                                  !ifndef LCD_MODEL { LCD_MODEL = 12864 }

; ******** Source: ../lib\gfx\bitmap.asm
     1                          ; 6502 - Bitmap
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          ;
    10                          
    11                          ; Bitmap object has the following structure
    12                          ;
    13                          ; Width
    14                          ; Height
    15                          
    16                          HAVE_BITMAP = 1
    17                          
    18                          !ifndef BITMAP_ZP_START { BITMAP_ZP_START = $28
    19                                  !warn "BITMAP_ZP_START not provided. Defaulting to ", BITMAP_ZP_START
    20                          }
    21                          
    22                          !ifndef BITMAP_RAM_START { BITMAP_RAM_START = $7b80
    23                                  !warn "BITMAP_RAM_START not provided. Defaulting to ", BITMAP_RAM_START
    24                          }
    25                          
    26                          ; -------------------------
    27                          ; Zero page
    28                          ; -------------------------
    29                          PIX_ADDR                = BITMAP_ZP_START
    30                          BITMAP_ADDR_H           = BITMAP_ZP_START+2
    31                          BITMAP_ZP_SIZE          = 4
    32                          
    33                          ; -----------------------------------------------------------------------------
    34                          ; High RAM
    35                          ; -----------------------------------------------------------------------------
    36                          
    37                          BITMAP_X       = BITMAP_RAM_START + 1
    38                          BITMAP_Y       = BITMAP_RAM_START + 2
    39                          BITMAP_X1      = BITMAP_X
    40                          BITMAP_Y1      = BITMAP_Y
    41                          BITMAP_X2      = BITMAP_RAM_START + 3
    42                          BITMAP_Y2      = BITMAP_RAM_START + 4
    43                          
    44                          BITMAP_LINE_STYLE     = BITMAP_RAM_START + 7
    45                          BITMAP_LINE_STYLE_ODD = BITMAP_RAM_START + 8
    46                          
    47                          BITMAP_TMP1    = BITMAP_RAM_START + 9
    48                          BITMAP_TMP2    = BITMAP_RAM_START + 10
    49                          BITMAP_TMP3    = BITMAP_RAM_START + 11
    50                          BITMAP_TMP4    = BITMAP_RAM_START + 12
    51                          BITMAP_TMP5    = BITMAP_RAM_START + 13
    52                          BITMAP_TMP6    = BITMAP_RAM_START + 14
    53                          
    54                          BITMAP_RAM_SIZE = 16
    55                          
    56                          
    57                          !if BITMAP_ZP_END < (BITMAP_ZP_START + BITMAP_ZP_SIZE) {
    58                                  !error "BITMAP_ZP requires ",BITMAP_ZP_SIZE," bytes. Allocated ",BITMAP_ZP_END - BITMAP_ZP_START
    59                          }
    60                          
    61                          !if BITMAP_RAM_END < (BITMAP_RAM_START + BITMAP_RAM_SIZE) {
    62                                  !error "BITMAP_RAM requires ",BITMAP_RAM_SIZE," bytes. Allocated ",BITMAP_RAM_END - BITMAP_RAM_START
    63                          }
    64                          
    65                          
    66                          
    67                          ; -----------------------------------------------------------------------------
    68                          ; bitmapClear: Clear the bitmap
    69                          ; -----------------------------------------------------------------------------
    70                          ; Inputs:
    71                          ;  BITMAP_ADDR_H: Contains page-aligned address of 1-bit 128x64 bitmap
    72                          ; -----------------------------------------------------------------------------
    73                          bitmapClear:
    74  e9f9 a9ff                       lda #$ff
    75  e9fb 8d1d7b                     sta BITMAP_LINE_STYLE
    76  e9fe a900                       lda #0
    77                                  
    78                                  ; flow through.... danger?
    79                                  
    80                                  
    81                          ; -----------------------------------------------------------------------------
    82                          ; bitmapFill: Fill the bitmap with value in A
    83                          ; -----------------------------------------------------------------------------
    84                          ; Inputs:
    85                          ;  BITMAP_ADDR_H: Contains page-aligned address of 1-bit 128x64 bitmap
    86                          ;  A: The value to fill
    87                          ; -----------------------------------------------------------------------------
    88                          bitmapFill:
    89  ea00 8d1f7b                     sta BITMAP_TMP1
    90  ea03 a520                       lda BITMAP_ADDR_H
    91  ea05 851f                       sta PIX_ADDR + 1
    92  ea07 a200                       ldx #0
    93  ea09 861e                       stx PIX_ADDR
    94                          
    95  ea0b ad1f7b                     lda BITMAP_TMP1 
    96  ea0e a000                       ldy #0
    97  ea10 a204                       ldx #4
    98                          -
    99  ea12 911e                       sta (PIX_ADDR), y
   100  ea14 c8                         iny
   101  ea15 d0fb                       bne -
   102  ea17 e61f                       inc PIX_ADDR + 1
   103  ea19 ca                         dex
   104  ea1a d0f6                       bne -
   105                                  
   106  ea1c 60                         rts
   107                                  
   108                                  
   109                          ; -----------------------------------------------------------------------------
   110                          ; bitmapXor: XOR (invert) the entire bitmap
   111                          ; -----------------------------------------------------------------------------
   112                          ; Inputs:
   113                          ;  BITMAP_ADDR_H: Contains page-aligned address of 1-bit 128x64 bitmap
   114                          ; -----------------------------------------------------------------------------
   115                          bitmapXor:
   116  ea1d a520                       lda BITMAP_ADDR_H
   117  ea1f 851f                       sta PIX_ADDR + 1
   118  ea21 a200                       ldx #0
   119  ea23 861e                       stx PIX_ADDR
   120                          
   121  ea25 a000                       ldy #0
   122  ea27 a204                       ldx #4
   123                          -
   124  ea29 a9ff                       lda #$ff
   125  ea2b 511e                       eor (PIX_ADDR), y
   126  ea2d 911e                       sta (PIX_ADDR), y
   127                                  
   128  ea2f c8                         iny
   129  ea30 d0f7                       bne -
   130  ea32 e61f                       inc PIX_ADDR + 1
   131  ea34 ca                         dex
   132  ea35 d0f2                       bne -
   133                                  
   134  ea37 60                         rts
   135                                  
   136                          ; -----------------------------------------------------------------------------
   137                          ; _bitmapOffset: Set up the offset to the buffer based on X/Y (Internal use)
   138                          ; -----------------------------------------------------------------------------
   139                          ; Inputs:
   140                          ;  BITMAP_ADDR_H: Contains page-aligned address of 1-bit 128x64 bitmap
   141                          ;  BITMAP_X: X position (0 to 127)
   142                          ;  BITMAP_Y: Y position (0 to 63)
   143                          ; Outputs:
   144                          ;  PIX_ADDR: Set to byte at column 0 of row BITMAP_Y
   145                          ;  Y:            Y offset of byte within row (0 to 63)
   146                          ;  X:            Bit offset within the byte
   147                          ; -----------------------------------------------------------------------------
   148                          _bitmapOffset:
   149                          
   150  ea38 a520                       lda BITMAP_ADDR_H
   151  ea3a 851f                       sta PIX_ADDR + 1
   152  ea3c a200                       ldx #0
   153  ea3e 861e                       stx PIX_ADDR
   154                                  
   155  ea40 ad187b                     lda BITMAP_Y
   156  ea43 4a                         lsr
   157  ea44 4a                         lsr
   158  ea45 4a                         lsr
   159  ea46 4a                         lsr
   160  ea47 18                         clc
   161  ea48 651f                       adc PIX_ADDR + 1
   162  ea4a 851f                       sta PIX_ADDR + 1
   163                                  
   164  ea4c ad187b                     lda BITMAP_Y
   165  ea4f 290f                       and #$0f
   166  ea51 0a                         asl
   167  ea52 0a                         asl
   168  ea53 0a                         asl
   169  ea54 0a                         asl
   170  ea55 851e                       sta PIX_ADDR
   171                                  
   172  ea57 ad177b                     lda BITMAP_X
   173  ea5a 4a                         lsr
   174  ea5b 4a                         lsr
   175  ea5c 4a                         lsr
   176  ea5d a8                         tay       ; Y contains start byte offset in row
   177                                  
   178  ea5e ad177b                     lda BITMAP_X
   179  ea61 2907                       and #$07
   180  ea63 aa                         tax   ; X contains bit offset within byte (0 - 7)       
   181  ea64 60                         rts
   182                                  
   183                          ; -----------------------------------------------------------------------------
   184                          ; bitmapSetPixel: Set a pixel
   185                          ; -----------------------------------------------------------------------------
   186                          ; Inputs:
   187                          ;  BITMAP_ADDR_H: Contains page-aligned address of 1-bit 128x64 bitmap
   188                          ;  BITMAP_X: X position (0 to 127)
   189                          ;  BITMAP_Y: Y position (0 to 63)
   190                          ; -----------------------------------------------------------------------------
   191                          bitmapSetPixel:
   192                          
   193  ea65 2038ea                     jsr _bitmapOffset
   194                                  
   195  ea68 bd30e1                     lda tableBitFromLeft, x
   196                                  
   197  ea6b 111e                       ora (PIX_ADDR), y
   198  ea6d 911e                       sta (PIX_ADDR), y
   199                                  
   200  ea6f 60                         rts     
   201                                  
   202                          ; -----------------------------------------------------------------------------
   203                          ; bitmapClearPixel: Clear a pixel
   204                          ; -----------------------------------------------------------------------------
   205                          ; Inputs:
   206                          ;  BITMAP_ADDR_H: Contains page-aligned address of 1-bit 128x64 bitmap
   207                          ;  BITMAP_X: X position (0 to 127)
   208                          ;  BITMAP_Y: Y position (0 to 63)
   209                          ; -----------------------------------------------------------------------------
   210                          bitmapClearPixel:
   211                          
   212  ea70 2038ea                     jsr _bitmapOffset
   213                                  
   214  ea73 bd38e1                     lda tableInvBitFromLeft, x
   215                          
   216  ea76 311e                       and (PIX_ADDR), y
   217  ea78 911e                       sta (PIX_ADDR), y
   218                                  
   219  ea7a 60                         rts
   220                                  
   221                                  
   222                          ; -----------------------------------------------------------------------------
   223                          ; bitmapXorPixel: XOR a pixel
   224                          ; -----------------------------------------------------------------------------
   225                          ; Inputs:
   226                          ;  BITMAP_ADDR_H: Contains page-aligned address of 1-bit 128x64 bitmap
   227                          ;  BITMAP_X: X position (0 to 127)
   228                          ;  BITMAP_Y: Y position (0 to 63)
   229                          ; -----------------------------------------------------------------------------
   230                          bitmapXorPixel:
   231                          
   232  ea7b 2038ea                     jsr _bitmapOffset
   233                                  
   234  ea7e bd30e1                     lda tableBitFromLeft, x
   235                          
   236  ea81 511e                       eor (PIX_ADDR), y
   237  ea83 911e                       sta (PIX_ADDR), y
   238                                  
   239  ea85 60                         rts
   240                                  
   241                          ; -----------------------------------------------------------------------------
   242                          ; bitmapLineH: Output a horizontal line
   243                          ; -----------------------------------------------------------------------------
   244                          ; Inputs:
   245                          ;  BITMAP_ADDR_H: Contains page-aligned address of 1-bit 128x64 bitmap
   246                          ;  BITMAP_X1: Start X position (0 to 127)
   247                          ;  BITMAP_X2: End X position (0 to 127)
   248                          ;  BITMAP_Y:  Y position (0 to 63)
   249                          ; -----------------------------------------------------------------------------
   250                          bitmapLineH:
   251                          
   252                                  END_OFFSET   = BITMAP_TMP3
   253                                  START_BYTE   = BITMAP_TMP1
   254                                  END_BYTE     = BITMAP_TMP2
   255                                  TMP_STYLE    = BITMAP_TMP5
   256                          
   257  ea86 ad197b                     lda BITMAP_X2
   258  ea89 4a                         lsr
   259  ea8a 4a                         lsr
   260  ea8b 4a                         lsr
   261  ea8c 8d217b                     sta END_OFFSET  ; END_OFFSET contains end byte offset within the row
   262                          
   263  ea8f 2038ea                     jsr _bitmapOffset
   264                          
   265  ea92 ad1d7b                     lda BITMAP_LINE_STYLE
   266  ea95 8d237b                     sta TMP_STYLE
   267                                  
   268  ea98 a9ff                       lda #$ff
   269                                  
   270                          ; shift the bits to the right for the pixel offset
   271                          -
   272  ea9a e000                       cpx #0
   273  ea9c f013                       beq ++
   274  ea9e 4e237b                     lsr TMP_STYLE
   275  eaa1 900a                       bcc +
   276  eaa3 48                         pha
   277  eaa4 a980                       lda #$80
   278  eaa6 0d237b                     ora TMP_STYLE
   279  eaa9 8d237b                     sta TMP_STYLE
   280  eaac 68                         pla     
   281                          +
   282  eaad ca                         dex
   283  eaae 4a                         lsr
   284  eaaf b0e9                       bcs -  ; carry is always set
   285                          ++
   286  eab1 8d1f7b                     sta START_BYTE
   287                          
   288  eab4 ad197b                     lda BITMAP_X2
   289  eab7 2907                       and #$07
   290                                  
   291  eab9 aa                         tax   ; X contains bit offset within byte (0 - 7)       
   292                                  
   293  eaba a9ff                       lda #$ff
   294                                  
   295                          ; shift the bits to the left for the pixel offset
   296                          -
   297  eabc e007                       cpx #7
   298  eabe f004                       beq +
   299  eac0 e8                         inx
   300  eac1 0a                         asl    
   301  eac2 b0f8                       bcs -  ; carry is always set
   302                          +
   303  eac4 8d207b                     sta END_BYTE
   304                                  
   305  eac7 ad1f7b                     lda START_BYTE
   306  eaca cc217b                     cpy END_OFFSET
   307  eacd d015                       bne ++
   308  eacf 2d207b                     and END_BYTE  ; combine if within the same byte
   309                                  
   310  ead2 48                         pha
   311  ead3 49ff                       eor #$ff
   312  ead5 311e                       and (PIX_ADDR), y
   313  ead7 8d227b                     sta BITMAP_TMP4
   314  eada 68                         pla
   315  eadb 2d237b                     and TMP_STYLE
   316  eade 0d227b                     ora BITMAP_TMP4
   317  eae1 911e                       sta (PIX_ADDR), y
   318                                  
   319  eae3 60                         rts
   320                          ++
   321  eae4 48                         pha
   322  eae5 49ff                       eor #$ff
   323  eae7 311e                       and (PIX_ADDR), y
   324  eae9 8d227b                     sta BITMAP_TMP4
   325  eaec 68                         pla
   326  eaed 2d237b                     and TMP_STYLE
   327  eaf0 0d227b                     ora BITMAP_TMP4
   328  eaf3 911e                       sta (PIX_ADDR), y
   329                          -
   330  eaf5 a9ff                       lda #$ff
   331  eaf7 c8                         iny
   332  eaf8 cc217b                     cpy END_OFFSET
   333  eafb d003                       bne +
   334  eafd 2d207b                     and END_BYTE  ; combine if within the same byte
   335                          +
   336  eb00 48                         pha
   337  eb01 49ff                       eor #$ff
   338  eb03 311e                       and (PIX_ADDR), y
   339  eb05 8d227b                     sta BITMAP_TMP4
   340  eb08 68                         pla
   341  eb09 2d237b                     and TMP_STYLE
   342  eb0c 0d227b                     ora BITMAP_TMP4
   343  eb0f 911e                       sta (PIX_ADDR), y
   344                          
   345  eb11 cc217b                     cpy END_OFFSET
   346  eb14 d0df                       bne -   
   347                                  
   348  eb16 60                         rts
   349                                  
   350                                  
   351                          ; -----------------------------------------------------------------------------
   352                          ; bitmapLineV: Output a horizontal line
   353                          ; -----------------------------------------------------------------------------
   354                          ; Inputs:
   355                          ;  BITMAP_ADDR_H: Contains page-aligned address of 1-bit 128x64 bitmap
   356                          ;  BITMAP_Y1: Start Y position (0 to 63)
   357                          ;  BITMAP_Y2: End Y position (0 to 63)
   358                          ;  BITMAP_X:  Y position (0 to 127)
   359                          ; -----------------------------------------------------------------------------
   360                          bitmapLineV:
   361                          
   362                                  COL_BYTE     = BITMAP_TMP1
   363                                  STYLE_BYTE   = BITMAP_TMP2
   364                          
   365  eb17 2038ea                     jsr _bitmapOffset
   366                                  
   367  eb1a ad1d7b                     lda BITMAP_LINE_STYLE
   368  eb1d 8d207b                     sta STYLE_BYTE
   369                                  
   370  eb20 bd30e1                     lda tableBitFromLeft, x
   371                          
   372  eb23 8d1f7b                     sta COL_BYTE    
   373                                  
   374  eb26 ae187b                     ldx BITMAP_Y1
   375                          -
   376  eb29 a980                       lda #$80
   377  eb2b 2c207b                     bit STYLE_BYTE
   378  eb2e d00c                       bne +
   379                                  ; draw a 0
   380  eb30 ad1f7b                     lda COL_BYTE
   381  eb33 49ff                       eor #$ff
   382  eb35 311e                       and (PIX_ADDR), y       
   383  eb37 911e                       sta (PIX_ADDR), y
   384  eb39 4c43eb                     jmp ++
   385                          +       ; draw a 1
   386  eb3c ad1f7b                     lda COL_BYTE    
   387  eb3f 111e                       ora (PIX_ADDR), y       
   388  eb41 911e                       sta (PIX_ADDR), y
   389                          ++
   390                                          
   391  eb43 ec1a7b                     cpx BITMAP_Y2
   392  eb46 f017                       beq ++
   393  eb48 0e207b                     asl STYLE_BYTE
   394  eb4b 9003                       bcc +
   395  eb4d ee207b                     inc STYLE_BYTE
   396                          +
   397  eb50 e8                         inx
   398  eb51 a910                       lda #16
   399  eb53 18                         clc
   400  eb54 651e                       adc PIX_ADDR
   401  eb56 9002                       bcc +
   402  eb58 e61f                       inc PIX_ADDR + 1
   403                          +
   404  eb5a 851e                       sta PIX_ADDR
   405  eb5c 18                         clc
   406  eb5d 90ca                       bcc -
   407                          ++
   408                                  
   409  eb5f 60                         rts
   410                          
   411                          ; -----------------------------------------------------------------------------
   412                          ; bitmapLine: Output an arbitrary line
   413                          ; -----------------------------------------------------------------------------
   414                          ; Inputs:
   415                          ;  BITMAP_ADDR_H: Contains page-aligned address of 1-bit 128x64 bitmap
   416                          ;  BITMAP_X1: 
   417                          ;  BITMAP_Y1: 
   418                          ;  BITMAP_X2: 
   419                          ;  BITMAP_Y2: 
   420                          ; -----------------------------------------------------------------------------
   421                          bitmapLine:
   422                          
   423                                  LINE_WIDTH = BITMAP_TMP1
   424                                  LINE_HEIGHT = BITMAP_TMP2
   425                                  
   426                                  ; get width
   427  eb60 ad197b                     lda BITMAP_X2
   428  eb63 38                         sec
   429  eb64 ed177b                     sbc BITMAP_X1
   430                                  
   431  eb67 1012                       bpl +
   432  eb69 ad177b                     lda BITMAP_X1
   433  eb6c 48                         pha
   434  eb6d ad197b                     lda BITMAP_X2
   435  eb70 8d177b                     sta BITMAP_X1
   436  eb73 68                         pla
   437  eb74 8d197b                     sta BITMAP_X2
   438  eb77 38                         sec
   439  eb78 ed177b                     sbc BITMAP_X1   
   440                          +       
   441  eb7b 8d1f7b                     sta LINE_WIDTH
   442                          
   443                                  ; get height
   444  eb7e ad1a7b                     lda BITMAP_Y2
   445  eb81 38                         sec
   446  eb82 ed187b                     sbc BITMAP_Y1
   447                          
   448  eb85 1012                       bpl +
   449  eb87 ad187b                     lda BITMAP_Y1
   450  eb8a 48                         pha
   451  eb8b ad1a7b                     lda BITMAP_Y2
   452  eb8e 8d187b                     sta BITMAP_Y1
   453  eb91 68                         pla
   454  eb92 8d1a7b                     sta BITMAP_Y2
   455  eb95 38                         sec
   456  eb96 ed187b                     sbc BITMAP_Y1   
   457                          +       
   458  eb99 8d207b                     sta LINE_HEIGHT
   459                                  
   460  eb9c cd1f7b                     cmp LINE_WIDTH
   461  eb9f b003                       bcs .goTall
   462  eba1 4ca7eb                     jmp _bitmapLineWide
   463                          .goTall
   464  eba4 4cf8eb                     jmp _bitmapLineTall
   465                                  
   466                                  ; rts in above subroutines
   467                                  
   468                          ; ----------------------------------------------------------------------------
   469                          
   470                          _bitmapLineWide:  ; a line that is wider than it is tall
   471                                  
   472                                  D = BITMAP_TMP6
   473                                  
   474                                  Y = BITMAP_TMP3
   475                                  
   476  eba7 ad207b                     lda LINE_HEIGHT
   477  ebaa 0a                         asl
   478  ebab 38                         sec
   479  ebac ed1f7b                     sbc LINE_WIDTH
   480  ebaf 8d247b                     sta D
   481                                  
   482  ebb2 ad177b                     lda BITMAP_X
   483  ebb5 48                         pha
   484                                  
   485  ebb6 ad187b                     lda BITMAP_Y1
   486  ebb9 8d217b                     sta Y
   487                                  
   488                          -
   489  ebbc 2065ea                     jsr bitmapSetPixel
   490  ebbf ad247b                     lda D
   491  ebc2 1007                       bpl +
   492  ebc4 ad207b                     lda LINE_HEIGHT
   493  ebc7 0a                         asl
   494  ebc8 4cdbeb                     jmp ++
   495                          +
   496  ebcb ee187b                 inc BITMAP_Y1
   497  ebce ad1f7b                     lda LINE_WIDTH
   498  ebd1 38                         sec
   499  ebd2 ed207b                     sbc LINE_HEIGHT
   500  ebd5 0a                         asl
   501  ebd6 49ff                       eor #$ff
   502  ebd8 18                         clc
   503  ebd9 6901                       adc #1
   504                          ++
   505  ebdb 18                         clc
   506  ebdc 6d247b                     adc D
   507  ebdf 8d247b                     sta D
   508  ebe2 ee177b                     inc BITMAP_X
   509  ebe5 ad197b                     lda BITMAP_X2
   510  ebe8 cd177b                     cmp BITMAP_X
   511  ebeb b0cf                       bcs -
   512                                  
   513  ebed ad217b                     lda Y
   514  ebf0 8d187b                     sta BITMAP_Y1
   515                                  
   516  ebf3 68                         pla
   517  ebf4 8d177b                     sta BITMAP_X
   518                                  
   519  ebf7 60                         rts
   520                                  
   521                          _bitmapLineTall:  ; a line that is taller than it is wide
   522                                  
   523                                  D = BITMAP_TMP6
   524                                  
   525                                  X = BITMAP_TMP3
   526                                  
   527  ebf8 ad1f7b                     lda LINE_WIDTH
   528  ebfb 0a                         asl
   529  ebfc 38                         sec
   530  ebfd ed207b                     sbc LINE_HEIGHT
   531  ec00 8d247b                     sta D
   532                                  
   533  ec03 ad187b                     lda BITMAP_Y
   534  ec06 48                         pha
   535                                  
   536  ec07 ad177b                     lda BITMAP_X1
   537  ec0a 8d217b                     sta X
   538                                  
   539                          -
   540  ec0d 2065ea                     jsr bitmapSetPixel
   541  ec10 ad247b                     lda D
   542  ec13 1007                       bpl +
   543  ec15 ad1f7b                     lda LINE_WIDTH
   544  ec18 0a                         asl
   545  ec19 4c2cec                     jmp ++
   546                          +
   547  ec1c ee177b                 inc BITMAP_X1
   548  ec1f ad207b                     lda LINE_HEIGHT
   549  ec22 38                         sec
   550  ec23 ed1f7b                     sbc LINE_WIDTH
   551  ec26 0a                         asl
   552  ec27 49ff                       eor #$ff
   553  ec29 18                         clc
   554  ec2a 6901                       adc #1
   555                          ++
   556  ec2c 18                         clc
   557  ec2d 6d247b                     adc D
   558  ec30 8d247b                     sta D
   559  ec33 ee187b                     inc BITMAP_Y
   560  ec36 ad1a7b                     lda BITMAP_Y2
   561  ec39 cd187b                     cmp BITMAP_Y
   562  ec3c b0cf                       bcs -
   563                          
   564  ec3e ad217b                     lda X
   565  ec41 8d177b                     sta BITMAP_X1
   566                                  
   567  ec44 68                         pla
   568  ec45 8d187b                     sta BITMAP_Y
   569                                  
   570  ec48 60                         rts
   571                                  
   572                          ; -----------------------------------------------------------------------------
   573                          ; bitmapRect: Output a rectangle outline
   574                          ; -----------------------------------------------------------------------------
   575                          ; Inputs:
   576                          ;  BITMAP_ADDR_H: Contains page-aligned address of 1-bit 128x64 bitmap
   577                          ;  BITMAP_X1: 
   578                          ;  BITMAP_Y1: 
   579                          ;  BITMAP_X2: 
   580                          ;  BITMAP_Y2: 
   581                          ; -----------------------------------------------------------------------------
   582                          bitmapRect:
   583  ec49 2086ea                     jsr bitmapLineH
   584  ec4c 2017eb                     jsr bitmapLineV
   585                                  
   586  ec4f ad177b                     lda BITMAP_X1
   587  ec52 48                         pha
   588  ec53 ad197b                     lda BITMAP_X2
   589  ec56 8d177b                     sta BITMAP_X1
   590                          
   591  ec59 2017eb                     jsr bitmapLineV
   592                                  
   593  ec5c 68                         pla
   594  ec5d 8d177b                     sta BITMAP_X1
   595                          
   596  ec60 ad187b                     lda BITMAP_Y1
   597  ec63 48                         pha
   598  ec64 ad1a7b                     lda BITMAP_Y2
   599  ec67 8d187b                     sta BITMAP_Y1
   600                                  
   601  ec6a 2086ea                     jsr bitmapLineH
   602                          
   603  ec6d 68                         pla
   604  ec6e 8d187b                     sta BITMAP_Y1
   605                                  
   606  ec71 60                         rts
   607                                  
   608                          ; -----------------------------------------------------------------------------
   609                          ; bitmapFilledRect: Output a filled rectangle
   610                          ; -----------------------------------------------------------------------------
   611                          ; Inputs:
   612                          ;  BITMAP_ADDR_H: Contains page-aligned address of 1-bit 128x64 bitmap
   613                          ;  BITMAP_X1: 
   614                          ;  BITMAP_Y1: 
   615                          ;  BITMAP_X2: 
   616                          ;  BITMAP_Y2: 
   617                          ; -----------------------------------------------------------------------------
   618                          bitmapFilledRect:
   619  ec72 ad187b                     lda BITMAP_Y1
   620  ec75 48                         pha
   621  ec76 ad1d7b                     lda BITMAP_LINE_STYLE
   622  ec79 48                         pha
   623                                  
   624                          -
   625  ec7a 2086ea                     jsr bitmapLineH
   626  ec7d ee187b                     inc BITMAP_Y1
   627                          
   628  ec80 68                         pla
   629  ec81 8d1d7b                     sta BITMAP_LINE_STYLE
   630  ec84 48                         pha
   631                                  
   632  ec85 ad1a7b                     lda BITMAP_Y2
   633  ec88 cd187b                     cmp BITMAP_Y1
   634  ec8b f014                       beq +
   635                          
   636  ec8d 2086ea                     jsr bitmapLineH
   637  ec90 ee187b                     inc BITMAP_Y1
   638                                  
   639  ec93 ad1e7b                     lda BITMAP_LINE_STYLE_ODD
   640  ec96 8d1d7b                     sta BITMAP_LINE_STYLE
   641                                  
   642  ec99 ad1a7b                     lda BITMAP_Y2
   643  ec9c cd187b                     cmp BITMAP_Y1
   644  ec9f d0d9                       bne -
   645                          +       
   646                          
   647  eca1 68                         pla
   648  eca2 8d1d7b                     sta BITMAP_LINE_STYLE
   649  eca5 68                         pla
   650  eca6 8d187b                     sta BITMAP_Y1
   651                                  

; ******** Source: kernel.asm
   167  eca9 60                 

; ******** Source: ../lib\lcd\lcd.asm
     1                          ; 6502 LCD - HBC-56
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          
    10                          !ifndef LCD_IO_PORT { LCD_IO_PORT = $02
    11                                  !warn "LCD_IO_PORT not provided. Defaulting to ", LCD_IO_PORT
    12                          }
    13                          
    14                          !ifndef LCD_ZP_START { LCD_ZP_START = $38
    15                                  !warn "LCD_ZP_START not provided. Defaulting to ", LCD_ZP_START
    16                          }
    17                          
    18                          !ifndef LCD_RAM_START { LCD_RAM_START = $7c00
    19                                  !warn "LCD_RAM_START not provided. Defaulting to ", LCD_RAM_START
    20                          }
    21                          
    22                          HAVE_LCD = 1
    23                          
    24                          ; -------------------------
    25                          ; Zero page
    26                          ; -------------------------
    27                          LCD_TMP1        = LCD_ZP_START
    28                          LCD_TMP2        = LCD_ZP_START + 1
    29                          LCD_ZP_SIZE     = 2
    30                          
    31                          
    32                          ; -------------------------
    33                          ; High RAM
    34                          ; -------------------------
    35                          .LCD_BUFFER_ADDR        = LCD_RAM_START
    36                          .LCD_REGY_TMP           = LCD_RAM_START + 40
    37                          LCD_RAM_SIZE            = 42
    38                          
    39                          
    40                          !if LCD_ZP_END < (LCD_ZP_START + LCD_ZP_SIZE) {
    41                                  !error "LCD_ZP requires ",LCD_ZP_SIZE," bytes. Allocated ",LCD_ZP_END - LCD_ZP_START
    42                          }
    43                          
    44                          !if LCD_RAM_END < (LCD_RAM_START + LCD_RAM_SIZE) {
    45                                  !error "LCD_RAM requires ",LCD_RAM_SIZE," bytes. Allocated ",LCD_RAM_END - LCD_RAM_START
    46                          }
    47                          
    48                          
    49                          
    50                          ; -------------------------
    51                          ; Contants
    52                          ; -------------------------
    53                          
    54                          ; IO Ports
    55                          LCD_CMD         = IO_PORT_BASE_ADDRESS | LCD_IO_PORT
    56                          LCD_DATA        = IO_PORT_BASE_ADDRESS | LCD_IO_PORT | $01
    57                          
    58                          ; Commands
    59                          LCD_CMD_CLEAR                   = %00000001
    60                          LCD_CMD_HOME                    = %00000010
    61                          
    62                          LCD_CMD_ENTRY_MODE              = %00000100
    63                          LCD_CMD_ENTRY_MODE_INCREMENT    = %00000010
    64                          LCD_CMD_ENTRY_MODE_DECREMENT    = %00000000
    65                          LCD_CMD_ENTRY_MODE_SHIFT        = %00000001
    66                          
    67                          LCD_CMD_DISPLAY                 = %00001000
    68                          LCD_CMD_DISPLAY_ON              = %00000100
    69                          LCD_CMD_DISPLAY_CURSOR          = %00000010
    70                          LCD_CMD_DISPLAY_CURSOR_BLINK    = %00000001
    71                          
    72                          LCD_CMD_SHIFT                   = %00010000
    73                          LCD_CMD_SHIFT_CURSOR            = %00000000
    74                          LCD_CMD_SHIFT_DISPLAY           = %00001000
    75                          LCD_CMD_SHIFT_LEFT              = %00000000
    76                          LCD_CMD_SHIFT_RIGHT             = %00000100
    77                          
    78                          LCD_CMD_SET_CGRAM_ADDR          = $40
    79                          LCD_CMD_SET_DRAM_ADDR           = $80
    80                          
    81                          LCD_CMD_FUNCTIONSET             = $20
    82                          LCD_CMD_8BITMODE                = $10
    83                          LCD_CMD_2LINE                   = $08
    84                          
    85                          !ifndef LCD_MODEL {
    86                                  !warn "Set LCD_MODEL to one of: 1602, 2004 or 12864. Defaulting to 1602"
    87                                  LCD_MODEL = 1602
    88                          }
    89                          

; ******** Source: ../lib\lcd\lcd.inc
     1                          ; 6502 LCD Macros - HBC-56
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          
    10                          ; -----------------------------------------------------------------------------
    11                          ; lcdPrint: Print immediate text
    12                          ; -----------------------------------------------------------------------------
    13                          ; Inputs:
    14                          ;  str: String to print
    15                          ; -----------------------------------------------------------------------------
    16                          !macro lcdPrint str {
    17                                  jmp +
    18                          .textAddr
    19                                  !text str,0
    20                          +
    21                                  lda #<.textAddr
    22                                  sta STR_ADDR_L
    23                                  lda #>.textAddr
    24                                  sta STR_ADDR_H
    25                                  jsr lcdPrint
    26                          }
    27                          
    28                          
    29                          ; -----------------------------------------------------------------------------
    30                          ; lcdChar: Print immediate character
    31                          ; -----------------------------------------------------------------------------
    32                          ; Inputs:
    33                          ;  c: Character to print
    34                          ; -----------------------------------------------------------------------------
    35                          !macro lcdChar c {
    36                                  pha
    37                                  lda #c
    38                                  jsr lcdChar
    39                                  pla
    40                          }
    41                          
    42                          
    43                          ; -----------------------------------------------------------------------------
    44                          ; lcdConsolePrint: Print immediate text to console
    45                          ; -----------------------------------------------------------------------------
    46                          ; Inputs:
    47                          ;  str: String to print
    48                          ; -----------------------------------------------------------------------------
    49                          !macro lcdConsolePrint .str {
    50                                  jmp .afterText
    51                          .textAddr
    52                                  !text .str,0
    53                          .afterText        
    54                          
    55                                  lda #<.textAddr
    56                                  sta STR_ADDR_L
    57                                  lda #>.textAddr
    58                                  sta STR_ADDR_H
    59                                  jsr lcdConsolePrint        

; ******** Source: ../lib\lcd\lcd.asm
    90                          
    91                          
    92                          ; -------------------------
    93                          ; Constants
    94                          ; -------------------------
    95                          !if LCD_MODEL = 1602 {
    96                                  LCD_ROWS = 2
    97                                  LCD_COLUMNS = 16
    98                                  LCD_GRAPHICS = 0
    99                                  LCD_ADDR_LINE1 = 0x00
   100                                  LCD_ADDR_LINE2 = 0x40
   101                          } else { !if LCD_MODEL = 2004 {
   102                                  LCD_ROWS = 4
   103                                  LCD_COLUMNS = 20
   104                                  LCD_GRAPHICS = 0
   105                                  LCD_ADDR_LINE1 = 0x00
   106                                  LCD_ADDR_LINE2 = 0x40
   107                                  LCD_ADDR_LINE3 = 0x14
   108                                  LCD_ADDR_LINE4 = 0x54
   109                          } else { !if LCD_MODEL = 12864 {
   110                                  LCD_ROWS = 4
   111                                  LCD_COLUMNS = 16
   112                                  LCD_GRAPHICS = 1
   113                                  LCD_ADDR_LINE1 = 0x00
   114                                  LCD_ADDR_LINE2 = 0x10
   115                                  LCD_ADDR_LINE3 = 0x08
   116                                  LCD_ADDR_LINE4 = 0x18

; ******** Source: ../lib\lcd\lcd12864b.asm
     1                          ; 6502 12864B LCD - HBC-56
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          
    10                          
    11                          HAVE_GRAPHICS_LCD = 1
    12                          
    13                          ; -------------------------
    14                          ; Constants
    15                          ; -------------------------
    16                          LCD_CMD_12864B_EXTENDED         = $04
    17                          LCD_CMD_EXT_GRAPHICS_ENABLE     = $02
    18                          LCD_CMD_EXT_GRAPHICS_ADDR       = $80
    19                          
    20                          
    21                          LCD_BASIC           = LCD_INITIALIZE
    22                          LCD_EXTENDED        = LCD_INITIALIZE | LCD_CMD_12864B_EXTENDED
    23                          
    24                          ;---------------------------
    25                          
    26                          
    27                          ; -----------------------------------------------------------------------------
    28                          ; lcdGraphicsMode: Initialise the LCD graphics mode
    29                          ; -----------------------------------------------------------------------------
    30                          lcdGraphicsMode:
    31  ecaa 20c7ed                     jsr lcdWait
    32  ecad a93c                       lda #LCD_EXTENDED
    33  ecaf 8d027f                     sta LCD_CMD
    34                          
    35  ecb2 20c7ed                     jsr lcdWait
    36  ecb5 a93e                       lda #LCD_EXTENDED | LCD_CMD_EXT_GRAPHICS_ENABLE
    37  ecb7 8d027f                     sta LCD_CMD
    38  ecba 60                         rts
    39                          
    40                          ; -----------------------------------------------------------------------------
    41                          ; lcdTextMode: Initialise the LCD text mode
    42                          ; -----------------------------------------------------------------------------
    43                          lcdTextMode:
    44  ecbb 20c7ed                     jsr lcdWait
    45  ecbe a93c                       lda #LCD_EXTENDED
    46  ecc0 8d027f                     sta LCD_CMD
    47                          
    48  ecc3 20c7ed                     jsr lcdWait
    49  ecc6 a93c                       lda #LCD_EXTENDED
    50  ecc8 8d027f                     sta LCD_CMD
    51  eccb 60                         rts
    52                          
    53                          
    54                          ; -----------------------------------------------------------------------------
    55                          ; lcdSetRow: Set LCD address to graphics row
    56                          ; -----------------------------------------------------------------------------
    57                          ; Inputs:
    58                          ;  Y: Row of the LCD (0 - 63)
    59                          ; -----------------------------------------------------------------------------
    60                          lcdGraphicsSetRow:
    61  eccc 48                         pha
    62                          
    63                                  ; set y address (0 - 31)
    64  eccd 20c7ed                     jsr lcdWait
    65  ecd0 98                         tya
    66  ecd1 291f                       and #$1f  ; only want 0-31
    67  ecd3 0980                       ora #LCD_CMD_EXT_GRAPHICS_ADDR
    68  ecd5 8d027f                     sta LCD_CMD
    69                          
    70                                  ; set x address - either 0 or 8
    71  ecd8 20c7ed                     jsr lcdWait
    72  ecdb 98                         tya
    73  ecdc 2920                       and #$20
    74  ecde 4a                         lsr
    75  ecdf 4a                         lsr
    76  ece0 0980                       ora #LCD_CMD_EXT_GRAPHICS_ADDR
    77  ece2 8d027f                     sta LCD_CMD
    78                          
    79  ece5 68                         pla
    80  ece6 60                         rts
    81                          
    82                          
    83                          ; -----------------------------------------------------------------------------
    84                          ; lcdImage: Output a full-screen image from memory (XY upper-left)
    85                          ; -----------------------------------------------------------------------------
    86                          ; Inputs:
    87                          ;  BITMAP_ADDR_H: Contains page-aligned address of 1-bit 128x64 bitmap
    88                          ; -----------------------------------------------------------------------------
    89                          lcdImage:
    90                          
    91  ece7 a520                       lda BITMAP_ADDR_H
    92  ece9 851f                       sta PIX_ADDR + 1
    93  eceb a200                       ldx #0
    94  eced 861e                       stx PIX_ADDR
    95                          
    96                          .imageLoop:
    97                          
    98                                  ; x in the range 0-63
    99                          
   100                                  ; set y address
   101  ecef 20c7ed                     jsr lcdWait
   102  ecf2 8a                         txa
   103  ecf3 291f                       and #$1f  ; only want 0-31
   104  ecf5 0980                       ora #LCD_CMD_EXT_GRAPHICS_ADDR
   105  ecf7 8d027f                     sta LCD_CMD
   106                          
   107                                  ; set x address - either 0 or 8
   108  ecfa 20c7ed                     jsr lcdWait
   109  ecfd 8a                         txa
   110  ecfe 2920                       and #$20
   111  ed00 4a                         lsr
   112  ed01 4a                         lsr
   113  ed02 0980                       ora #LCD_CMD_EXT_GRAPHICS_ADDR
   114  ed04 8d027f                     sta LCD_CMD
   115                          
   116                          
   117  ed07 a000                       ldy #0
   118                          .imgRowLoop
   119  ed09 20c7ed                     jsr lcdWait
   120                                  
   121  ed0c b11e                       lda (PIX_ADDR), y
   122  ed0e 8d037f                     sta LCD_DATA
   123                                  
   124  ed11 c8                         iny
   125  ed12 c010                       cpy #16
   126  ed14 d0f3                       bne .imgRowLoop
   127                                  
   128  ed16 a51e                       lda PIX_ADDR
   129  ed18 18                         clc
   130  ed19 6910                       adc #16
   131  ed1b 9002                       bcc +
   132  ed1d e61f                       inc PIX_ADDR + 1
   133                          +
   134  ed1f 851e                       sta PIX_ADDR
   135                          
   136  ed21 e8                         inx
   137  ed22 e040                       cpx #64
   138  ed24 d0c9                       bne .imageLoop
   139                          
   140  ed26 60                         rts
   141                                  
   142                                  
   143                          ; -----------------------------------------------------------------------------
   144                          ; lcdImageVflip: Output a full-screen image from memory (XY lower-left)
   145                          ; -----------------------------------------------------------------------------
   146                          ; Inputs:
   147                          ;  BITMAP_ADDR_H: Contains page-aligned address of 1-bit 128x64 bitmap
   148                          ; -----------------------------------------------------------------------------
   149                          lcdImageVflip:
   150                          
   151  ed27 a520                       lda BITMAP_ADDR_H
   152  ed29 18                         clc
   153  ed2a 6903                       adc #3
   154  ed2c 851f                       sta PIX_ADDR + 1
   155  ed2e a2f0                       ldx #240
   156  ed30 861e                       stx PIX_ADDR
   157  ed32 a200                       ldx #0
   158                          
   159                          .imageLoopV:
   160                          
   161                                  ; x in the range 0-63
   162                          
   163                                  ; set y address
   164  ed34 20c7ed                     jsr lcdWait
   165  ed37 8a                         txa
   166  ed38 291f                       and #$1f  ; only want 0-31
   167  ed3a 0980                       ora #LCD_CMD_EXT_GRAPHICS_ADDR
   168  ed3c 8d027f                     sta LCD_CMD
   169                          
   170                                  ; set x address - either 0 or 8
   171  ed3f 20c7ed                     jsr lcdWait
   172  ed42 8a                         txa
   173  ed43 2920                       and #$20
   174  ed45 4a                         lsr
   175  ed46 4a                         lsr
   176  ed47 0980                       ora #LCD_CMD_EXT_GRAPHICS_ADDR
   177  ed49 8d027f                     sta LCD_CMD
   178                          
   179                          
   180  ed4c a000                       ldy #0
   181                          .imgRowLoopV
   182  ed4e 20c7ed                     jsr lcdWait
   183                                  
   184  ed51 b11e                       lda (PIX_ADDR), y
   185  ed53 8d037f                     sta LCD_DATA
   186                                  
   187  ed56 c8                         iny
   188  ed57 c010                       cpy #16
   189  ed59 d0f3                       bne .imgRowLoopV
   190                                  
   191  ed5b a51e                       lda PIX_ADDR
   192  ed5d 38                         sec
   193  ed5e e910                       sbc #16
   194  ed60 b004                       bcs +
   195  ed62 a9f0                       lda #240
   196  ed64 c61f                       dec PIX_ADDR + 1
   197                          +
   198  ed66 851e                       sta PIX_ADDR
   199                          
   200  ed68 e8                         inx
   201  ed69 e040                       cpx #64
   202  ed6b d0c7                       bne .imageLoopV
   203                          
   204  ed6d 60                         rts

; ******** Source: ../lib\lcd\lcd.asm
   117                          
   118                          } else {
   119                                  !error "Unknown LCD_MODEL. Must be one of: 1602, 2004 or 12864"
   120                          }}}
   121                          
   122                          
   123                          LCD_INITIALIZE  = LCD_CMD_FUNCTIONSET | LCD_CMD_8BITMODE | LCD_CMD_2LINE
   124                          DISPLAY_MODE    = LCD_CMD_DISPLAY | LCD_CMD_DISPLAY_ON
   125                          
   126                          ASCII_NEWLINE = 10
   127                          
   128                          ; -----------------------------------------------------------------------------
   129                          ; lcdInit: Initialise the LCD
   130                          ; -----------------------------------------------------------------------------
   131                          lcdInit:
   132  ed6e 20c7ed                     jsr lcdWait
   133  ed71 a938                       lda #LCD_INITIALIZE
   134  ed73 8d027f                     sta LCD_CMD
   135  ed76 2080ed                     jsr lcdClear
   136  ed79 2089ed                     jsr lcdHome
   137  ed7c 209bed                     jsr lcdDisplayOff
   138  ed7f 60                         rts
   139                          
   140                          
   141                          ; -----------------------------------------------------------------------------
   142                          ; lcdClear: Clears the LCD
   143                          ; -----------------------------------------------------------------------------
   144                          lcdClear:
   145  ed80 20c7ed                     jsr lcdWait
   146  ed83 a901                       lda #LCD_CMD_CLEAR
   147  ed85 8d027f                     sta LCD_CMD
   148  ed88 60                         rts     
   149                          
   150                          ; -----------------------------------------------------------------------------
   151                          ; lcdHome: Return to the start address
   152                          ; -----------------------------------------------------------------------------
   153                          lcdHome:
   154  ed89 20c7ed                     jsr lcdWait
   155  ed8c a902                       lda #LCD_CMD_HOME
   156  ed8e 8d027f                     sta LCD_CMD
   157  ed91 60                         rts     
   158                          
   159                          ; -----------------------------------------------------------------------------
   160                          ; lcdDisplayOn: Turn the display on
   161                          ; -----------------------------------------------------------------------------
   162                          lcdDisplayOn:
   163  ed92 20c7ed                     jsr lcdWait
   164  ed95 a90c                       lda #DISPLAY_MODE
   165  ed97 8d027f                     sta LCD_CMD
   166  ed9a 60                         rts
   167                          
   168                          ; -----------------------------------------------------------------------------
   169                          ; lcdDisplayOff: Turn the display off
   170                          ; -----------------------------------------------------------------------------
   171                          lcdDisplayOff:
   172  ed9b 20c7ed                     jsr lcdWait
   173  ed9e a908                       lda #LCD_CMD_DISPLAY
   174  eda0 8d027f                     sta LCD_CMD
   175  eda3 60                         rts
   176                          
   177                          ; -----------------------------------------------------------------------------
   178                          ; lcdCursorOn: Show cursor
   179                          ; -----------------------------------------------------------------------------
   180                          lcdCursorOn:
   181  eda4 20c7ed                     jsr lcdWait
   182  eda7 a90e                       lda #DISPLAY_MODE | LCD_CMD_DISPLAY_CURSOR
   183  eda9 8d027f                     sta LCD_CMD
   184  edac 60                         rts     
   185                          
   186                          ; -----------------------------------------------------------------------------
   187                          ; lcdCursorOff: Hide cursor
   188                          ; -----------------------------------------------------------------------------
   189                          lcdCursorOff:
   190  edad 20c7ed                     jsr lcdWait
   191  edb0 a90c                       lda #DISPLAY_MODE
   192  edb2 8d027f                     sta LCD_CMD
   193  edb5 60                         rts     
   194                          
   195                          ; -----------------------------------------------------------------------------
   196                          ; lcdCursorBlinkOn: Show cursor
   197                          ; -----------------------------------------------------------------------------
   198                          lcdCursorBlinkOn:
   199  edb6 20c7ed                     jsr lcdWait
   200  edb9 a90f                       lda #DISPLAY_MODE | LCD_CMD_DISPLAY_CURSOR | LCD_CMD_DISPLAY_CURSOR_BLINK
   201  edbb 8d027f                     sta LCD_CMD
   202  edbe 60                         rts     
   203                          
   204                          ; -----------------------------------------------------------------------------
   205                          ; lcdDetect: Do we have an LCD plugged in?
   206                          ; -----------------------------------------------------------------------------
   207                          ; Outputs:
   208                          ;  C: 1 if exists. 0 if not
   209                          ; -----------------------------------------------------------------------------
   210                          lcdDetect:
   211  edbf 18                         clc
   212  edc0 ad027f                     lda LCD_CMD
   213  edc3 d001                       bne +
   214  edc5 38                         sec
   215                          +
   216  edc6 60                         rts
   217                          
   218                          
   219                          ; -----------------------------------------------------------------------------
   220                          ; lcdWait: Wait until the LCD is no longer busy
   221                          ; -----------------------------------------------------------------------------
   222                          ; Outputs:
   223                          ;  A: Current LCD address
   224                          ; -----------------------------------------------------------------------------
   225                          lcdWait:
   226  edc7 ad027f                     lda LCD_CMD
   227  edca 30fb                       bmi lcdWait  ; branch if bit 7 is set
   228  edcc 60                         rts
   229                          
   230                          ; -----------------------------------------------------------------------------
   231                          ; lcdWaitPreserve: Wait until the LCD is no longer busy Preserves A, address in x
   232                          ; -----------------------------------------------------------------------------
   233                          lcdWaitPreserve:
   234  edcd ac027f                     ldy LCD_CMD
   235  edd0 30fb                       bmi lcdWaitPreserve; branch if bit 7 is set
   236  edd2 60                         rts
   237                          
   238                          ; -----------------------------------------------------------------------------
   239                          ; lcdRead: Read a character from the LCD
   240                          ; -----------------------------------------------------------------------------
   241                          ; Outputs:
   242                          ;  A: Character read
   243                          ; -----------------------------------------------------------------------------
   244                          lcdRead:
   245  edd3 20c7ed                     jsr lcdWait
   246  edd6 ad037f                     lda LCD_DATA
   247  edd9 60                         rts
   248                          
   249                          ; -----------------------------------------------------------------------------
   250                          ; lcdPrint: Print a null-terminated string
   251                          ; -----------------------------------------------------------------------------
   252                          ; Inputs:
   253                          ;  STR_ADDR: Contains address of null-terminated string
   254                          ; -----------------------------------------------------------------------------
   255                          lcdPrint:
   256  edda a000                       ldy #0
   257                          -
   258  eddc 20c7ed                     jsr lcdWait
   259  eddf b134                       lda (STR_ADDR), y
   260  ede1 f012                       beq ++
   261  ede3 c90a                       cmp #ASCII_NEWLINE ; check for newline
   262  ede5 d007                       bne +
   263  ede7 20b8ef                     jsr lcdNextLine
   264  edea c8                         iny
   265  edeb 4cdced                     jmp -
   266                          + 
   267  edee 8d037f                     sta LCD_DATA
   268  edf1 c8                         iny
   269  edf2 4cdced                     jmp -
   270                          ++
   271  edf5 60                         rts
   272                          
   273                          ; -----------------------------------------------------------------------------
   274                          ; lcdChar: Output a character
   275                          ; -----------------------------------------------------------------------------
   276                          ; Inputs:
   277                          ;  A: The character to output
   278                          ; -----------------------------------------------------------------------------
   279                          lcdChar:
   280  edf6 20cded                     jsr lcdWaitPreserve
   281  edf9 8d037f                     sta LCD_DATA
   282  edfc 60                         rts
   283                          
   284                          ; -----------------------------------------------------------------------------
   285                          ; lcdCharScroll: Output a character, scroll if required
   286                          ; -----------------------------------------------------------------------------
   287                          ; Inputs:
   288                          ;  A: The character to output
   289                          ; -----------------------------------------------------------------------------
   290                          lcdCharScroll:
   291  edfd 20cded                     jsr lcdWaitPreserve
   292  ee00 8d037f                     sta LCD_DATA
   293                          
   294                                  ; Y is previous address
   295  ee03 20cfee                     jsr lcdCurrentLine
   296  ee06 8528                       sta LCD_TMP1
   297  ee08 20cded                     jsr lcdWaitPreserve
   298  ee0b 20cfee                     jsr lcdCurrentLine
   299  ee0e 4528                       eor LCD_TMP1
   300  ee10 f007                       beq +
   301  ee12 e628                       inc LCD_TMP1
   302  ee14 a528                       lda LCD_TMP1
   303  ee16 4c69ef                     jmp lcdGotoLine
   304                          +
   305  ee19 60                         rts
   306                          
   307                          ; -----------------------------------------------------------------------------
   308                          ; lcdBackspace: Backspace a character
   309                          ; -----------------------------------------------------------------------------
   310                          lcdBackspace:
   311  ee1a 20cded                     jsr lcdWaitPreserve
   312                                  ; Y is previous address
   313  ee1d 20cfee                     jsr lcdCurrentLine
   314  ee20 8528                       sta LCD_TMP1
   315                          
   316  ee22 a910                       lda #LCD_CMD_SHIFT | LCD_CMD_SHIFT_LEFT
   317  ee24 8d027f                     sta LCD_CMD
   318  ee27 20c7ed                     jsr lcdWait
   319  ee2a 20cded                     jsr lcdWaitPreserve
   320  ee2d 20cfee                     jsr lcdCurrentLine
   321  ee30 4528                       eor LCD_TMP1
   322  ee32 f009                       beq +
   323  ee34 c628                       dec LCD_TMP1
   324  ee36 3005                       bmi +
   325  ee38 a528                       lda LCD_TMP1
   326  ee3a 4cd2ee                     jmp lcdGotoLineEnd
   327                          +
   328  ee3d 20c7ed                     jsr lcdWait
   329  ee40 a920                       lda #' '
   330  ee42 8d037f                     sta LCD_DATA
   331  ee45 20c7ed                     jsr lcdWait
   332  ee48 a910                       lda #LCD_CMD_SHIFT | LCD_CMD_SHIFT_LEFT
   333  ee4a 8d027f                     sta LCD_CMD
   334                          
   335  ee4d 60                         rts
   336                          
   337                          ; -----------------------------------------------------------------------------
   338                          ; lcdInt8: Output an 8-bit integer
   339                          ; -----------------------------------------------------------------------------
   340                          ; Inputs:
   341                          ;  A: The value to output
   342                          ; -----------------------------------------------------------------------------
   343                          lcdInt8:
   344                          
   345                          .B = LCD_TMP1
   346                          .C = LCD_TMP2
   347                          
   348  ee4e 48                         pha
   349  ee4f a201                       ldx #1
   350  ee51 8629                       stx .C
   351  ee53 e8                         inx
   352  ee54 a040                       ldy #$40
   353                          --
   354  ee56 8428                       sty .B
   355  ee58 4a                         lsr
   356                          -
   357  ee59 2a                         rol
   358  ee5a b005                       bcs +
   359  ee5c dd81ee                     cmp .A, x
   360  ee5f 9004                       bcc ++
   361                          + 
   362  ee61 fd81ee                     sbc .A, x
   363  ee64 38                         sec
   364                          ++ 
   365  ee65 2628                       rol .B
   366  ee67 90f0                       bcc -
   367  ee69 a8                         tay
   368  ee6a e429                       cpx .C
   369  ee6c a528                       lda .B
   370  ee6e 9004                       bcc +
   371  ee70 f007                       beq ++
   372  ee72 8629                       stx .C
   373                          +
   374  ee74 4930                       eor #$30
   375  ee76 20f6ed                     jsr lcdChar
   376                          ++
   377  ee79 98                         tya
   378  ee7a a010                       ldy #$10
   379  ee7c ca                         dex
   380  ee7d 10d7                       bpl --
   381  ee7f 68                         pla
   382  ee80 60                         rts
   383                          
   384  ee81 80a0c8             .A !byte 128,160,200
   385                          
   386                          
   387                          ; -----------------------------------------------------------------------------
   388                          ; lcdHex8: Output an 8-bit byte as hexadecimal
   389                          ; -----------------------------------------------------------------------------
   390                          ; Inputs:
   391                          ;  A: The value to output
   392                          ; -----------------------------------------------------------------------------
   393                          lcdHex8:
   394  ee84 48                         pha
   395  ee85 4a                         lsr
   396  ee86 4a                         lsr
   397  ee87 4a                         lsr
   398  ee88 4a                         lsr
   399  ee89 aa                         tax
   400  ee8a bd9dee                     lda .H, x
   401  ee8d 20f6ed                     jsr lcdChar
   402  ee90 68                         pla
   403  ee91 48                         pha
   404  ee92 290f                       and #$0f
   405  ee94 aa                         tax
   406  ee95 bd9dee                     lda .H, x
   407  ee98 20f6ed                     jsr lcdChar
   408  ee9b 68                         pla
   409  ee9c 60                         rts
   410                          
   411  ee9d 3031323334353637....H !text "0123456789abcdef"
   412                          
   413                          
   414                          !if LCD_ROWS > 2 {
   415                          
   416                          lcdCurrentLine4:
   417  eead c018                       cpy #LCD_ADDR_LINE4
   418  eeaf b00e                       bcs .lcdLine4
   419  eeb1 c010                       cpy #LCD_ADDR_LINE2
   420  eeb3 b017                       bcs .lcdLine2
   421  eeb5 c008                       cpy #LCD_ADDR_LINE3
   422  eeb7 b003                       bcs .lcdLine3
   423  eeb9 4cc9ee                     jmp .lcdLine1
   424                          
   425                          .lcdLine3
   426  eebc a903                       lda #3
   427  eebe 60                         rts
   428                          
   429                          .lcdLine4
   430  eebf a904                       lda #4
   431  eec1 60                         rts
   432                          
   433                          } ; LCD_ROWS > 2
   434                          
   435                          lcdCurrentLine2:
   436  eec2 c010                       cpy #LCD_ADDR_LINE1+LCD_COLUMNS;16;LCD_ADDR_LINE2
   437  eec4 9003                       bcc .lcdLine1
   438  eec6 4cccee                     jmp .lcdLine2
   439                          
   440                          .lcdLine1
   441  eec9 a901                       lda #1
   442  eecb 60                         rts
   443                          
   444                          .lcdLine2
   445  eecc a902                       lda #2
   446  eece 60                         rts
   447                          
   448                          ; -----------------------------------------------------------------------------
   449                          ; lcdCurrentLine: Return the current line/row
   450                          ; -----------------------------------------------------------------------------
   451                          lcdCurrentLine:
   452                          !if LCD_ROWS > 2 {
   453  eecf 4cadee                     jmp lcdCurrentLine4
   454                          } else {
   455                                  jmp lcdCurrentLine2
   456                          }
   457                          
   458                          
   459                          
   460                          ; -----------------------------------------------------------------------------
   461                          ; lcdGotoLineEnd: Go to end of line in 'A'
   462                          ; -----------------------------------------------------------------------------
   463                          lcdGotoLineEnd:
   464                          !if LCD_ROWS > 2 {
   465  eed2 c904                       cmp #4
   466  eed4 f071                       beq lcdLineFourEnd
   467  eed6 c903                       cmp #3
   468  eed8 f04b                       beq lcdLineThreeEnd
   469                          }
   470  eeda c902                       cmp #2
   471  eedc f025                       beq lcdLineTwoEnd
   472  eede 4ce1ee                     jmp lcdLineOneEnd
   473                          
   474                          
   475                          ; -----------------------------------------------------------------------------
   476                          ; lcdLineOneEnd: Move cursor to end of line 1
   477                          ; -----------------------------------------------------------------------------
   478                          lcdLineOneEnd:
   479  eee1 48                         pha
   480                          !if LCD_MODEL = 12864 {
   481  eee2 a987                       lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE1) + (LCD_COLUMNS/2) - 1
   482  eee4 8d027f                     sta LCD_CMD
   483  eee7 20d3ed                     jsr lcdRead
   484  eeea 48                         pha
   485  eeeb a987                       lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE1) + (LCD_COLUMNS/2) - 1
   486  eeed 8d027f                     sta LCD_CMD
   487  eef0 a920                       lda #' '
   488  eef2 20f6ed                     jsr lcdChar
   489  eef5 20f6ed                     jsr lcdChar
   490  eef8 a987                       lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE1) + (LCD_COLUMNS/2) - 1
   491  eefa 8d027f                     sta LCD_CMD
   492  eefd 68                         pla
   493  eefe 20f6ed                     jsr lcdChar
   494                          } else {
   495                                  lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE1) + (LCD_COLUMNS) - 2
   496                                  sta LCD_CMD
   497                                  jsr lcdRead
   498                                  pha
   499                                  lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE1) + (LCD_COLUMNS) - 2
   500                                  sta LCD_CMD
   501                                  lda #' '
   502                                  jsr lcdChar
   503                                  jsr lcdChar
   504                                  lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE1) + (LCD_COLUMNS) - 2
   505                                  sta LCD_CMD
   506                                  pla
   507                                  jsr lcdChar
   508                          }
   509  ef01 68                         pla
   510  ef02 60                         rts
   511                          
   512                          ; -----------------------------------------------------------------------------
   513                          ; lcdLineTwoEnd: Move cursor to end of line 2
   514                          ; -----------------------------------------------------------------------------
   515                          lcdLineTwoEnd:
   516  ef03 48                         pha
   517                          !if LCD_MODEL = 12864 {
   518  ef04 a997                       lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE2) + (LCD_COLUMNS/2) - 1
   519  ef06 8d027f                     sta LCD_CMD
   520  ef09 20d3ed                     jsr lcdRead
   521  ef0c 48                         pha
   522  ef0d a997                       lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE2) + (LCD_COLUMNS/2) - 1
   523  ef0f 8d027f                     sta LCD_CMD
   524  ef12 a920                       lda #' '
   525  ef14 20f6ed                     jsr lcdChar
   526  ef17 20f6ed                     jsr lcdChar
   527  ef1a a997                       lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE2) + (LCD_COLUMNS/2) - 1
   528  ef1c 8d027f                     sta LCD_CMD
   529  ef1f 68                         pla
   530  ef20 20f6ed                     jsr lcdChar
   531                          } else {
   532                                  lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE2) + (LCD_COLUMNS) - 2
   533                                  sta LCD_CMD
   534                                  jsr lcdRead
   535                                  pha
   536                                  lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE2) + (LCD_COLUMNS) - 2
   537                                  sta LCD_CMD
   538                                  lda #' '
   539                                  jsr lcdChar
   540                                  jsr lcdChar
   541                                  lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE2) + (LCD_COLUMNS) - 2
   542                                  sta LCD_CMD
   543                                  pla
   544                                  jsr lcdChar
   545                          }
   546  ef23 68                         pla
   547  ef24 60                         rts
   548                          
   549                          
   550                           !if LCD_ROWS > 2 {
   551                          ; -----------------------------------------------------------------------------
   552                          ; lcdLineThreeEnd: Move cursor to end of line 3
   553                          ; -----------------------------------------------------------------------------
   554                          lcdLineThreeEnd:
   555  ef25 48                         pha
   556                          !if LCD_MODEL = 12864 {
   557  ef26 a98f                       lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE3) + (LCD_COLUMNS/2) - 1
   558  ef28 8d027f                     sta LCD_CMD
   559  ef2b 20d3ed                     jsr lcdRead
   560  ef2e 48                         pha
   561  ef2f a98f                       lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE3) + (LCD_COLUMNS/2) - 1
   562  ef31 8d027f                     sta LCD_CMD
   563  ef34 a920                       lda #' '
   564  ef36 20f6ed                     jsr lcdChar
   565  ef39 20f6ed                     jsr lcdChar
   566  ef3c a98f                       lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE3) + (LCD_COLUMNS/2) - 1
   567  ef3e 8d027f                     sta LCD_CMD
   568  ef41 68                         pla
   569  ef42 20f6ed                     jsr lcdChar
   570                          } else {
   571                                  lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE3) + (LCD_COLUMNS) - 2
   572                                  sta LCD_CMD
   573                                  jsr lcdRead
   574                                  pha
   575                                  lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE3) + (LCD_COLUMNS) - 2
   576                                  sta LCD_CMD
   577                                  lda #' '
   578                                  jsr lcdChar
   579                                  jsr lcdChar
   580                                  lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE3) + (LCD_COLUMNS) - 2
   581                                  sta LCD_CMD
   582                                  pla
   583                                  jsr lcdChar
   584                          }
   585  ef45 68                         pla
   586  ef46 60                         rts
   587                          
   588                          ; -----------------------------------------------------------------------------
   589                          ; lcdLineFourEnd: Move cursor to end of line 4
   590                          ; -----------------------------------------------------------------------------
   591                          lcdLineFourEnd:
   592  ef47 48                         pha
   593                          !if LCD_MODEL = 12864 {
   594  ef48 a99f                       lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE4) + (LCD_COLUMNS/2) - 1
   595  ef4a 8d027f                     sta LCD_CMD
   596  ef4d 20d3ed                     jsr lcdRead
   597  ef50 48                         pha
   598  ef51 a99f                       lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE4) + (LCD_COLUMNS/2) - 1
   599  ef53 8d027f                     sta LCD_CMD
   600  ef56 a920                       lda #' '
   601  ef58 20f6ed                     jsr lcdChar
   602  ef5b 20f6ed                     jsr lcdChar
   603  ef5e a99f                       lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE4) + (LCD_COLUMNS/2) - 1
   604  ef60 8d027f                     sta LCD_CMD
   605  ef63 68                         pla
   606  ef64 20f6ed                     jsr lcdChar
   607                          } else {
   608                                  lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE4) + (LCD_COLUMNS) - 2
   609                                  sta LCD_CMD
   610                                  jsr lcdRead
   611                                  pha
   612                                  lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE4) + (LCD_COLUMNS) - 2
   613                                  sta LCD_CMD
   614                                  lda #' '
   615                                  jsr lcdChar
   616                                  jsr lcdChar
   617                                  lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE4) + (LCD_COLUMNS) - 2
   618                                  sta LCD_CMD
   619                                  pla
   620                                  jsr lcdChar
   621                          }
   622  ef67 68                         pla
   623  ef68 60                         rts
   624                          
   625                          
   626                          } ; LCD_ROWS > 2
   627                          
   628                          ; -----------------------------------------------------------------------------
   629                          ; lcdGotoLine: Go to line in 'A'
   630                          ; -----------------------------------------------------------------------------
   631                          lcdGotoLine:
   632                          !if LCD_ROWS > 2 {
   633  ef69 c904                       cmp #4
   634  ef6b f027                       beq lcdLineFour
   635  ef6d c903                       cmp #3
   636  ef6f f01b                       beq lcdLineThree
   637                          }
   638  ef71 c902                       cmp #2
   639  ef73 f00f                       beq lcdLineTwo
   640  ef75 c901                       cmp #1
   641  ef77 f003                       beq lcdLineOne
   642  ef79 4cccef                     jmp lcdScrollUp
   643                          
   644                          
   645                          ; -----------------------------------------------------------------------------
   646                          ; lcdLineOne: Move cursor to line 1
   647                          ; -----------------------------------------------------------------------------
   648                          lcdLineOne:
   649  ef7c 48                         pha
   650  ef7d a980                       lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE1)
   651  ef7f 8d027f                     sta LCD_CMD
   652  ef82 68                         pla
   653  ef83 60                         rts
   654                          
   655                          ; -----------------------------------------------------------------------------
   656                          ; lcdLineTwo: Move cursor to line 2
   657                          ; -----------------------------------------------------------------------------
   658                          lcdLineTwo:
   659  ef84 48                         pha
   660  ef85 a990                       lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE2)
   661  ef87 8d027f                     sta LCD_CMD
   662  ef8a 68                         pla
   663  ef8b 60                         rts
   664                          
   665                          
   666                           !if LCD_ROWS > 2 {
   667                          ; -----------------------------------------------------------------------------
   668                          ; lcdLineThree: Move cursor to line 3
   669                          ; -----------------------------------------------------------------------------
   670                          lcdLineThree:
   671  ef8c 48                         pha
   672  ef8d a988                       lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE3)
   673  ef8f 8d027f                     sta LCD_CMD
   674  ef92 68                         pla
   675  ef93 60                         rts
   676                          
   677                          ; -----------------------------------------------------------------------------
   678                          ; lcdLineFour: Move cursor to line 4
   679                          ; -----------------------------------------------------------------------------
   680                          lcdLineFour:
   681  ef94 48                         pha
   682  ef95 a998                       lda #(LCD_CMD_SET_DRAM_ADDR | LCD_ADDR_LINE4)
   683  ef97 8d027f                     sta LCD_CMD
   684  ef9a 68                         pla
   685  ef9b 60                         rts
   686                           
   687                          ; -----------------------------------------------------------------------------
   688                          ; lcdNextLine4: Move cursor to next line (4-row LCD version)
   689                          ; -----------------------------------------------------------------------------
   690                          lcdNextLine4:
   691  ef9c 20c7ed                     jsr lcdWait
   692                                  ; A now contains address
   693  ef9f c918                       cmp #LCD_ADDR_LINE4
   694  efa1 b029                       bcs lcdScrollUp
   695  efa3 c910                       cmp #LCD_ADDR_LINE2
   696  efa5 b0e5                       bcs lcdLineThree
   697  efa7 c908                       cmp #LCD_ADDR_LINE3
   698  efa9 b0e9                       bcs lcdLineFour
   699                                  
   700  efab 4c84ef                     jmp lcdLineTwo
   701                           }
   702                           
   703                          
   704                          ; -----------------------------------------------------------------------------
   705                          ; lcdNextLine2: Move cursor to next line (2-row LCD version)
   706                          ; -----------------------------------------------------------------------------
   707                          lcdNextLine2:
   708  efae 20c7ed                     jsr lcdWait
   709                                  ; A now contains address
   710  efb1 c910                       cmp #LCD_ADDR_LINE2
   711  efb3 b017                       bcs lcdScrollUp
   712  efb5 4c84ef                     jmp lcdLineTwo
   713                          
   714                          ; -----------------------------------------------------------------------------
   715                          ; lcdNextLine: Move cursor to next line
   716                          ; -----------------------------------------------------------------------------
   717                          lcdNextLine:
   718                          !if LCD_ROWS > 2 {
   719  efb8 4c9cef                     jmp lcdNextLine4
   720                          } else {
   721                                  jmp lcdNextLine2
   722                          }
   723                          
   724                          ; -----------------------------------------------------------------------------
   725                          ; lcdReadLine: Reads a line from the display
   726                          ; -----------------------------------------------------------------------------
   727                          ; Inputs:
   728                          ;  STR_ADDR: Contains address to output null-terminated line to
   729                          ; -----------------------------------------------------------------------------
   730                          lcdReadLine:
   731  efbb a000                       ldy #0
   732                          -
   733  efbd 20d3ed                     jsr lcdRead
   734  efc0 9134                       sta (STR_ADDR), y
   735  efc2 c8                         iny
   736  efc3 c010                       cpy #LCD_COLUMNS
   737  efc5 d0f6                       bne -
   738  efc7 a900                       lda #0
   739  efc9 9134                       sta (STR_ADDR), y
   740  efcb 60                         rts
   741                          
   742                          ; -----------------------------------------------------------------------------
   743                          ; lcdScrollUp: Scroll the LCD up one line
   744                          ; -----------------------------------------------------------------------------
   745                          lcdScrollUp:
   746  efcc 48                         pha
   747                          
   748  efcd 20aded                     jsr lcdCursorOff
   749                          
   750  efd0 a958                       lda #<.LCD_BUFFER_ADDR
   751  efd2 8534                       sta STR_ADDR_L
   752  efd4 a97b                       lda #>.LCD_BUFFER_ADDR
   753  efd6 8535                       sta STR_ADDR_H
   754                          
   755  efd8 20c7ed                     jsr lcdWait
   756  efdb 2084ef                     jsr lcdLineTwo
   757  efde 20bbef                     jsr lcdReadLine
   758  efe1 20c7ed                     jsr lcdWait
   759  efe4 207cef                     jsr lcdLineOne
   760  efe7 20daed                     jsr lcdPrint
   761  efea 20c7ed                     jsr lcdWait
   762                          
   763                          !if LCD_ROWS > 2 {
   764                          
   765  efed 208cef                     jsr lcdLineThree
   766  eff0 20bbef                     jsr lcdReadLine
   767  eff3 20c7ed                     jsr lcdWait
   768  eff6 2084ef                     jsr lcdLineTwo
   769  eff9 20daed                     jsr lcdPrint
   770                                  
   771  effc 20c7ed                     jsr lcdWait
   772  efff 2094ef                     jsr lcdLineFour
   773  f002 20bbef                     jsr lcdReadLine
   774  f005 20c7ed                     jsr lcdWait
   775  f008 208cef                     jsr lcdLineThree
   776  f00b 20daed                     jsr lcdPrint
   777                                  
   778  f00e 20c7ed                     jsr lcdWait
   779  f011 2094ef                     jsr lcdLineFour
   780                          } else {
   781                                  jsr lcdLineTwo
   782                          }
   783                          
   784  f014 a210                       ldx #LCD_COLUMNS
   785                          -
   786  f016 48a92020f6ed68             +lcdChar ' '
   787  f01d ca                         dex
   788  f01e d0f6                       bne -
   789  f020 20c7ed                     jsr lcdWait
   790                          !if LCD_ROWS > 2 {
   791  f023 2094ef                     jsr lcdLineFour
   792                          } else {
   793                                  jsr lcdLineTwo
   794                          }
   795                          
   796  f026 20b6ed                     jsr lcdCursorBlinkOn
   797                          
   798  f029 68                         pla
   799  f02a 60                         rts
   800                          
   801                          ; -----------------------------------------------------------------------------
   802                          ; lcdConsoleOut: Print a null-terminated string
   803                          ; -----------------------------------------------------------------------------
   804                          ; Inputs:
   805                          ;  'A': Character to output to console
   806                          ; -----------------------------------------------------------------------------
   807                          lcdConsoleOut:
   808  f02b 8c807b                     sty .LCD_REGY_TMP
   809  f02e c90a                       cmp #ASCII_RETURN
   810  f030 f013                       beq .newline
   811  f032 c908                       cmp #ASCII_BACKSPACE
   812  f034 f015                       beq .backspace
   813  f036 c90d                       cmp #ASCII_CR   ; omit these
   814  f038 f007                       beq .endOut
   815  f03a c900                       cmp #0
   816  f03c f003                       beq .endOut
   817                          
   818                                  ; regular character
   819  f03e 20fded                     jsr lcdCharScroll ; outputs A to the LCD - auto-scrolls too :)
   820                          
   821                          .endOut:
   822  f041 ac807b                     ldy .LCD_REGY_TMP
   823  f044 60                         rts
   824                          
   825                          .newline
   826  f045 20b8ef                     jsr lcdNextLine ; scroll to the next line... scroll screen if on last line
   827  f048 4c41f0                     jmp .endOut
   828                          
   829                          .backspace
   830  f04b 201aee                     jsr lcdBackspace 
   831  f04e 4c41f0                     jmp .endOut
   832                          
   833                          ; -----------------------------------------------------------------------------
   834                          ; lcdConsolePrint: Print a null-terminated string (console mode)
   835                          ; -----------------------------------------------------------------------------
   836                          ; Inputs:
   837                          ;  STR_ADDR: Contains address of null-terminated string
   838                          ; -----------------------------------------------------------------------------
   839                          lcdConsolePrint:
   840  f051 a000                       ldy #0
   841                          -
   842  f053 b134                       lda (STR_ADDR), y
   843  f055 f006                       beq +
   844  f057 202bf0                     jsr lcdConsoleOut
   845  f05a c8                         iny
   846  f05b d0f6                       bne -
   847                          +
   848  f05d 60                         rts
   849                          

; ******** Source: kernel.asm
   168                          

; ******** Source: ../lib\gfx\tilemap.asm
     1                          ; 6502 - Tilemap
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          ;
    10                          ; Tilemap structure
    11                          ; ---------------------
    12                          ; BufferAddressH   (Page-aligned buffer - MSB)
    13                          ; Size
    14                          ; TilesetAddressH  (Page-aligned tilset - MSB)
    15                          ; InvertAddressH   (Page-aligned invert flags - MSB) (optional)
    16                          ; DirtyAddressH    (Page-aligned dirty flags - MSB)  (optional)
    17                          

; ******** Source: ../lib\gfx\tilemap.inc
     1                          ; 6502 - Tilemap
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          ;
    10                          
    11                          
    12                          
    13                          !macro tilemapCreate .tilemapStructAddr, .bufferAddr, .tilesetAddr, .sizeFlags, .tileSizePx, .invertAddr, .dirtyAddr {
    14                                  !if <.tilesetAddr != 0 { !error "tilemapCreate: Tileset address must be page-aligned",.tilesetAddr }
    15                                  !if >.tilesetAddr < 3 { !error "tilemapCreate: Tileset address must be greater than $2ff",.tilesetAddr }
    16                                  !if <.bufferAddr != 0 { !error "tilemapCreate: Buffer address must be page-aligned",.bufferAddr }
    17                                  !if >.bufferAddr < 3 { !error "tilemapCreate: Buffer address must be greater than $2ff",.bufferAddr }
    18                                  !if .invertAddr != 0 and <.invertAddr != 0  {!error "tilemapCreate: Invert address must be page-aligned", .invertAddr}
    19                                  !if .invertAddr != 0 and >.invertAddr < 3  {!error "tilemapCreate: Invert address must be greater than $2ff", .invertAddr}
    20                                  !if .dirtyAddr != 0 and <.dirtyAddr != 0  {!error "tilemapCreate: Dirty address must be page-aligned", .dirtyAddr}
    21                                  !if .dirtyAddr != 0 and >.dirtyAddr < 3  {!error "tilemapCreate: Dirty address must be greater than $2ff", .dirtyAddr}
    22                                  !if .tileSizePx != 4 and .tileSizePx != 8 {!error "tilemapCreate: Tile size must be 4 or 8 pixels",.tileSizePx}
    23                          
    24                                  lda #<.tilemapStructAddr
    25                                  sta TILEMAP_ADDR
    26                                  lda #>.tilemapStructAddr
    27                                  sta TILEMAP_ADDR + 1
    28                          
    29                                  lda #>.bufferAddr
    30                                  sta .tilemapStructAddr + TILEMAP_BUFFER_ADDR
    31                                  lda #.sizeFlags
    32                                  sta .tilemapStructAddr + TILEMAP_SIZE
    33                                  lda #>.tilesetAddr
    34                                  sta .tilemapStructAddr + TILEMAP_TILES_ADDR
    35                                  lda #>.invertAddr
    36                                  sta .tilemapStructAddr + TILEMAP_INVERT_ADDR
    37                                  lda #>.dirtyAddr
    38                                  sta .tilemapStructAddr + TILEMAP_DIRTY_ADDR
    39                                  lda #.tileSizePx
    40                                  sta .tilemapStructAddr + TILEMAP_TILE_SIZE_PX
    41                          
    42                                  jsr tilemapInit
    43                          }
    44                          
    45                          !macro tilemapCreateDefault .sizeFlags, .tilesetAddr {
    46                                  +tilemapCreate TILEMAP_FIXED_ADDRESS, TILEMAP_DEFAULT_BUFFER_ADDRESS, .tilesetAddr, .sizeFlags, 8, $0, $0
    47                          }
    48                          
    49                          !macro tilemapSetActive .tilemapStructAddr {
    50                                  lda #<.tilemapStructAddr
    51                                  sta TILEMAP_ADDR
    52                                  lda #>.tilemapStructAddr
    53                                  sta TILEMAP_ADDR + 1
    54                          
    55                                  jsr tilemapSetActive

; ******** Source: ../lib\gfx\tilemap.asm
    19                          
    20                          HAVE_TILEMAP = 1
    21                          
    22                          
    23                          !ifndef TILEMAP_ZP_START { TILEMAP_ZP_START = $20
    24                                  !warn "TILEMAP_ZP_START not provided. Defaulting to ", TILEMAP_ZP_START
    25                          }
    26                          
    27                          !ifndef TILEMAP_RAM_START { TILEMAP_RAM_START = $7a00
    28                                  !warn "TILEMAP_RAM_START not provided. Defaulting to ", TILEMAP_RAM_START
    29                          }
    30                          
    31                          !if (TILEMAP_RAM_START & $ff) != 0 {
    32                                  !error "TILEMAP_RAM_START must be on a page boundary"
    33                          }
    34                          
    35                          ; -------------------------
    36                          ; Tilemap structure
    37                          ; -------------------------
    38                          TILEMAP_BUFFER_ADDR     = 0                             ; High byte of page-aligned buffer
    39                          TILEMAP_SIZE            = 1     ; Size flags
    40                          TILEMAP_TILES_ADDR      = 2
    41                          TILEMAP_INVERT_ADDR     = 3     ; High byte of tilemap
    42                          TILEMAP_DIRTY_ADDR      = 4
    43                          TILEMAP_WIDTH_TILES     = 5
    44                          TILEMAP_HEIGHT_TILES    = 6
    45                          TILEMAP_TILE_SIZE_PX    = 7
    46                          TILEMAP_STRUCTURE_SIZE  = TILEMAP_TILE_SIZE_PX
    47                          
    48                          
    49                          ; -------------------------
    50                          ; Zero page
    51                          ; -------------------------
    52                          TILEMAP_ADDR            = TILEMAP_ZP_START
    53                          TILEMAP_TMP_BUFFER_ADDR = TILEMAP_ZP_START + 2
    54                          TILEMAP_TMP_TILES_ADDR  = TILEMAP_ZP_START + 4
    55                          TILEMAP_ZP_SIZE         = 6
    56                          
    57                          ; -----------------------------------------------------------------------------
    58                          ; High RAM
    59                          ; -----------------------------------------------------------------------------
    60                          TILEMAP_DEFAULT_BUFFER_ADDRESS = TILEMAP_RAM_START
    61                          
    62                          TILEMAP_TMP_BUF_ROW     = TILEMAP_RAM_START + $80
    63                          TILEMAP_TMP_BUF_COL     = TILEMAP_RAM_START + $81
    64                          TILEMAP_TMP_TILE_ROW    = TILEMAP_RAM_START + $82
    65                          TILEMAP_TMP_OUTPUT_ROW  = TILEMAP_RAM_START + $83
    66                          TILEMAP_TMP_1           = TILEMAP_RAM_START + $84
    67                          TILEMAP_TMP_2           = TILEMAP_RAM_START + $85
    68                          TILEMAP_TMP_TILES_W     = TILEMAP_RAM_START + $86
    69                          TILEMAP_TMP_TILES_H     = TILEMAP_RAM_START + $87
    70                          TILEMAP_TMP_TILE_SIZE   = TILEMAP_RAM_START + $88
    71                          
    72                          TILEMAP_FIXED_ADDRESS   = TILEMAP_RAM_START + $100
    73                          
    74                          TILEMAP_RAM_SIZE        = (TILEMAP_FIXED_ADDRESS + TILEMAP_STRUCTURE_SIZE) - TILEMAP_RAM_START
    75                          
    76                          
    77                          
    78                          !if TILEMAP_ZP_END < (TILEMAP_ZP_START + TILEMAP_ZP_SIZE) {
    79                                  !error "TILEMAP_ZP requires ",TILEMAP_ZP_SIZE," bytes. Allocated ",TILEMAP_ZP_END - TILEMAP_ZP_START
    80                          }
    81                          
    82                          !if TILEMAP_RAM_END < (TILEMAP_RAM_START + TILEMAP_RAM_SIZE) {
    83                                  !error "TILEMAP_RAM requires ",TILEMAP_RAM_SIZE," bytes. Allocated ",TILEMAP_RAM_END - TILEMAP_RAM_START
    84                          }
    85                          
    86                          ; -------------------------
    87                          ; Contants
    88                          ; -------------------------
    89                          TILEMAP_SIZE_X_16       = %00000000
    90                          TILEMAP_SIZE_X_32       = %00000001
    91                          TILEMAP_SIZE_X_64       = %00000010
    92                          TILEMAP_SIZE_Y_8        = %00000000
    93                          TILEMAP_SIZE_Y_16       = %00000100
    94                          TILEMAP_SIZE_Y_32       = %00001000
    95                          
    96                          TILE_SIZE               = 8     ; size of each tile (in px)
    97                          
    98                          
    99                          
   100                          
   101                          ; -----------------------------------------------------------------------------
   102                          ; tilemapInit: Initialise a tilemap
   103                          ; -----------------------------------------------------------------------------
   104                          ; Inputs:
   105                          ;  TILEMAP_ADDR: Address of tilemap structure
   106                          ; -----------------------------------------------------------------------------
   107                          tilemapInit:
   108  f05e a000                       ldy #0
   109  f060 8432                       sty MEM_LEN
   110  f062 8433                       sty MEM_LEN + 1
   111  f064 842e                       sty MEM_DST
   112  f066 b118                       lda (TILEMAP_ADDR), y  ; buffer address H
   113  f068 852f                       sta MEM_DST + 1
   114  f06a 851b                       sta TILEMAP_TMP_BUFFER_ADDR + 1
   115                          
   116  f06c a001                       ldy #TILEMAP_SIZE
   117                          
   118                          @MIN_WIDTH=16
   119                          @MIN_HEIGHT=8
   120                          
   121  f06e a910                       lda #@MIN_WIDTH         ; minimum width
   122  f070 8d817a                     sta TILEMAP_TMP_BUF_COL ; temporary storage for x tiles
   123  f073 a908                       lda #@MIN_HEIGHT        ; minimum height
   124  f075 8d807a                     sta TILEMAP_TMP_BUF_ROW ; temporary storage for y tiles
   125                          
   126  f078 a900                       lda #0
   127  f07a 8533                       sta MEM_LEN + 1
   128  f07c a980                       lda #(@MIN_WIDTH * @MIN_HEIGHT) ; base size (16 x 8)
   129  f07e 8532                       sta MEM_LEN                     ; size in bytes
   130  f080 b118                       lda (TILEMAP_ADDR), y           ; size flags
   131  f082 8d847a                     sta TILEMAP_TMP_1
   132  f085 f038                       beq ++
   133                          
   134                          
   135                                  ; check size flags, multiple size
   136  f087 a903                       lda #TILEMAP_SIZE_X_32 | TILEMAP_SIZE_X_64
   137  f089 2c847a                     bit TILEMAP_TMP_1
   138  f08c f015                       beq +
   139  f08e 0632                       asl MEM_LEN
   140  f090 2633                       rol MEM_LEN  + 1
   141  f092 0e817a                     asl TILEMAP_TMP_BUF_COL
   142  f095 a902                       lda #TILEMAP_SIZE_X_64
   143  f097 2c847a                     bit TILEMAP_TMP_1
   144  f09a f007                       beq +
   145  f09c 0632                       asl MEM_LEN
   146  f09e 2633                       rol MEM_LEN  + 1
   147  f0a0 0e817a                     asl TILEMAP_TMP_BUF_COL
   148                          +
   149  f0a3 a90c                       lda #TILEMAP_SIZE_Y_16 | TILEMAP_SIZE_Y_32
   150  f0a5 2c847a                     bit TILEMAP_TMP_1
   151  f0a8 f015                       beq ++
   152  f0aa 0632                       asl MEM_LEN
   153  f0ac 2633                       rol MEM_LEN  + 1
   154  f0ae 0e807a                     asl TILEMAP_TMP_BUF_ROW
   155  f0b1 a908                       lda #TILEMAP_SIZE_Y_32
   156  f0b3 2c847a                     bit TILEMAP_TMP_1
   157  f0b6 f007                       beq ++
   158  f0b8 0632                       asl MEM_LEN
   159  f0ba 2633                       rol MEM_LEN  + 1
   160  f0bc 0e807a                     asl TILEMAP_TMP_BUF_ROW
   161                          ++
   162                                  ; MEM_DST and MEM_LEN are set. clear the buffer.
   163  f0bf a900                       lda #$00
   164  f0c1 200de1                     jsr memsetMultiPage
   165                          
   166  f0c4 ad817a                     lda TILEMAP_TMP_BUF_COL
   167  f0c7 a005                       ldy #TILEMAP_WIDTH_TILES
   168  f0c9 9118                       sta (TILEMAP_ADDR), y
   169                          
   170  f0cb ad807a                     lda TILEMAP_TMP_BUF_ROW
   171  f0ce a006                       ldy #TILEMAP_HEIGHT_TILES
   172  f0d0 9118                       sta (TILEMAP_ADDR), y
   173                          
   174                                  ; todo: invert & dirty
   175                          
   176  f0d2 20d6f0                     jsr tilemapSetActive
   177                          
   178  f0d5 60                         rts
   179                          
   180                          ; -----------------------------------------------------------------------------
   181                          ; tilemapSetActive: Set the current/active tilemap
   182                          ; -----------------------------------------------------------------------------
   183                          ; Inputs:
   184                          ;  TILEMAP_ADDR: Address of tilemap structure
   185                          ; -----------------------------------------------------------------------------
   186                          tilemapSetActive:
   187  f0d6 a005                       ldy #TILEMAP_WIDTH_TILES
   188  f0d8 b118                       lda (TILEMAP_ADDR), y
   189  f0da 8d867a                     sta TILEMAP_TMP_TILES_W
   190                          
   191  f0dd a006                       ldy #TILEMAP_HEIGHT_TILES
   192  f0df b118                       lda (TILEMAP_ADDR), y
   193  f0e1 8d877a                     sta TILEMAP_TMP_TILES_H
   194                          
   195  f0e4 a007                       ldy #TILEMAP_TILE_SIZE_PX
   196  f0e6 b118                       lda (TILEMAP_ADDR), y
   197  f0e8 8d887a                     sta TILEMAP_TMP_TILE_SIZE
   198  f0eb 60                         rts
   199                          
   200                          
   201                          !if LCD_GRAPHICS=1 {
   202                          
   203                          ; -----------------------------------------------------------------------------
   204                          ; tilemapRenderRowToLcd: Render a row of the current/active tilemap
   205                          ; -----------------------------------------------------------------------------
   206                          ; Prerequisites:
   207                          ;  tilemapSetActive called for the tilemap
   208                          ; Inputs:
   209                          ;  y: Row to render (0-7)
   210                          ; -----------------------------------------------------------------------------
   211                          tilemapRenderRowToLcd:
   212  f0ec 98                         tya
   213  f0ed 2907                       and #$07
   214  f0ef 8d807a                     sta TILEMAP_TMP_BUF_ROW
   215  f0f2 8d857a                     sta TILEMAP_TMP_2
   216  f0f5 0a                         asl
   217  f0f6 0a                         asl
   218  f0f7 0a                         asl
   219  f0f8 8d837a                     sta TILEMAP_TMP_OUTPUT_ROW
   220                          
   221  f0fb ee857a                     inc TILEMAP_TMP_2
   222                          
   223                                  ; set the working tilemap buffer address
   224  f0fe a000                       ldy #TILEMAP_BUFFER_ADDR
   225  f100 b118                       lda (TILEMAP_ADDR), y
   226  f102 851b                       sta TILEMAP_TMP_BUFFER_ADDR + 1
   227                          
   228                                  ; reset temp variables to zero
   229  f104 a900                       lda #0
   230  f106 851a                       sta TILEMAP_TMP_BUFFER_ADDR ; LSB
   231  f108 851c                       sta TILEMAP_TMP_TILES_ADDR  ; LSB
   232  f10a 8d817a                     sta TILEMAP_TMP_BUF_COL
   233  f10d 8d827a                     sta TILEMAP_TMP_TILE_ROW
   234                          
   235  f110 4c31f1                     jmp .tilemapRenderFrom
   236                          
   237                          
   238                          ; -----------------------------------------------------------------------------
   239                          ; tilemapRenderToLcd: Render the current/active tilemap
   240                          ; -----------------------------------------------------------------------------
   241                          ; Prerequisites:
   242                          ;  tilemapSetActive called for the tilemap
   243                          ; -----------------------------------------------------------------------------
   244                          tilemapRenderToLcd:
   245                          
   246  f113 ad877a                     lda TILEMAP_TMP_TILES_H
   247  f116 8d857a                     sta TILEMAP_TMP_2
   248                          
   249                                  ; set the working tilemap buffer address
   250  f119 a000                       ldy #TILEMAP_BUFFER_ADDR
   251  f11b b118                       lda (TILEMAP_ADDR), y
   252  f11d 851b                       sta TILEMAP_TMP_BUFFER_ADDR + 1
   253                                  
   254                                  ; reset temp variables to zero
   255  f11f a900                       lda #0
   256  f121 851a                       sta TILEMAP_TMP_BUFFER_ADDR ; LSB
   257  f123 851c                       sta TILEMAP_TMP_TILES_ADDR  ; LSB
   258  f125 8d807a                     sta TILEMAP_TMP_BUF_ROW
   259  f128 8d817a                     sta TILEMAP_TMP_BUF_COL
   260  f12b 8d827a                     sta TILEMAP_TMP_TILE_ROW
   261  f12e 8d837a                     sta TILEMAP_TMP_OUTPUT_ROW
   262                          
   263                          .tilemapRenderFrom
   264  f131 ac837a                     ldy TILEMAP_TMP_OUTPUT_ROW
   265  f134 20ccec                     jsr lcdGraphicsSetRow
   266                          
   267                                  ; iterate over the buffer rows and columns
   268                          @renderRow
   269                          ;!byte $db
   270                          
   271  f137 a900                       lda #0
   272  f139 8d847a                     sta TILEMAP_TMP_1
   273                          
   274                                  ; set the working tileset address
   275  f13c a002                       ldy #TILEMAP_TILES_ADDR
   276  f13e b118                       lda (TILEMAP_ADDR), y
   277  f140 851d                       sta TILEMAP_TMP_TILES_ADDR + 1
   278                          
   279                                  ; get tile offset
   280  f142 ad807a                     lda TILEMAP_TMP_BUF_ROW
   281  f145 0a                         asl
   282  f146 0a                         asl
   283  f147 0a                         asl
   284  f148 0a                         asl
   285  f149 18                         clc
   286  f14a 6d817a                     adc TILEMAP_TMP_BUF_COL
   287  f14d a8                         tay
   288                          
   289                          
   290                                  ; load the tile index
   291  f14e b11a                       lda (TILEMAP_TMP_BUFFER_ADDR), y
   292                          
   293                                  ; multiply by 8 to get an offset into the tileset buffer
   294                                  ; storing overflow in TILEMAP_TMP_1
   295  f150 0a                         asl
   296  f151 2e847a                     rol TILEMAP_TMP_1
   297  f154 0a                         asl 
   298  f155 2e847a                     rol TILEMAP_TMP_1
   299  f158 0a                         asl
   300  f159 2e847a                     rol TILEMAP_TMP_1
   301                          
   302                                  ; add the tile row offset (the row of the current tile)
   303                                  ; and set as y index
   304  f15c 0d827a                     ora TILEMAP_TMP_TILE_ROW
   305  f15f a8                         tay
   306                          
   307                                  ; load the overflow and add to the MSB of the tileset address
   308  f160 ad847a                     lda TILEMAP_TMP_1
   309  f163 18                         clc
   310  f164 651d                       adc TILEMAP_TMP_TILES_ADDR + 1
   311  f166 851d                       sta TILEMAP_TMP_TILES_ADDR + 1
   312                          
   313  f168 20c7ed                     jsr lcdWait
   314                          
   315                                  ; load the byte from the tile
   316  f16b b11c                       lda (TILEMAP_TMP_TILES_ADDR), y
   317                          
   318                                  ; output the byte
   319  f16d 8d037f                     sta LCD_DATA
   320                          
   321                                  ; increment column and check against # columns
   322  f170 ee817a                     inc TILEMAP_TMP_BUF_COL
   323  f173 ad867a                     lda TILEMAP_TMP_TILES_W
   324  f176 cd817a                     cmp TILEMAP_TMP_BUF_COL
   325  f179 d0bc                       bne @renderRow
   326                          
   327                                  ; increment tile row (row within tile) and check against tile size
   328  f17b a900                       lda #0
   329  f17d 8d817a                     sta TILEMAP_TMP_BUF_COL
   330  f180 ee827a                     inc TILEMAP_TMP_TILE_ROW
   331  f183 ee837a                     inc TILEMAP_TMP_OUTPUT_ROW
   332  f186 ac837a                     ldy TILEMAP_TMP_OUTPUT_ROW
   333                          
   334  f189 20ccec                     jsr lcdGraphicsSetRow
   335                          
   336  f18c ad887a                     lda TILEMAP_TMP_TILE_SIZE
   337  f18f cd827a                     cmp TILEMAP_TMP_TILE_ROW
   338  f192 d0a3                       bne @renderRow
   339                          
   340                                  ; increment row and check against # rows
   341  f194 a900                       lda #0
   342  f196 8d827a                     sta TILEMAP_TMP_TILE_ROW
   343  f199 ee807a                     inc TILEMAP_TMP_BUF_ROW
   344  f19c ad857a                     lda TILEMAP_TMP_2
   345  f19f cd807a                     cmp TILEMAP_TMP_BUF_ROW
   346  f1a2 d093                       bne @renderRow
   347                          
   348  f1a4 60                         rts
   349                          

; ******** Source: kernel.asm
   169                          
   170                          }
   171                          
   172                          !ifndef HBC56_DISABLE_UART {

; ******** Source: ../lib\ser\uart.asm
     1                          ; 6502 - MC68B50 UART
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          
    10                          HAVE_UART = 1
    11                          
    12                          ; -------------------------
    13                          ; Constants
    14                          ; -------------------------
    15                          !ifndef UART_IO_PORT { UART_IO_PORT = $20
    16                                  !warn "UART_IO_PORT not provided. Defaulting to ", UART_IO_PORT
    17                          }
    18                          
    19                          !ifndef UART_ZP_START { UART_ZP_START = $40
    20                                  !warn "UART_ZP_START not provided. Defaulting to ", UART_ZP_START
    21                          }
    22                          
    23                          !ifndef UART_RAM_START { UART_RAM_START = $7c80
    24                                  !warn "UART_RAM_START not provided. Defaulting to ", UART_RAM_START
    25                          }
    26                          
    27                          
    28                          ; -----------------------------------------------------------------------------
    29                          ; Zero page
    30                          ; -----------------------------------------------------------------------------
    31                          UART_RX_BUFFER_HEAD  = UART_ZP_START            ; head of circular buffer
    32                          UART_RX_BUFFER_TAIL  = UART_ZP_START + 1        ; tail of circular buffer
    33                          UART_RX_BUFFER_BYTES = UART_ZP_START + 2        ; bytes in buffer
    34                          UART_RX_FLAGS        = UART_ZP_START + 3        ; flags
    35                          @UART_ZP_END         = UART_ZP_START + 4
    36                          
    37                          !if (.UART_ZP_SIZE < @UART_ZP_END - UART_ZP_START) {
    38                                  !error "UART ZP allocation insufficient. Allocated: ", .UART_ZP_SIZE, " Require: ", (@UART_ZP_END - UART_ZP_START)
    39                          }
    40                          
    41                          ; -----------------------------------------------------------------------------
    42                          ; High RAM
    43                          ; -----------------------------------------------------------------------------
    44                          UART_RX_BUFFER       = UART_RAM_START
    45                          UART_RX_BUFFER_SIZE  = $100
    46                          
    47                          @UART_RAM_END        = UART_RAM_START + UART_RX_BUFFER_SIZE
    48                          
    49                          !if (.UART_RAM_SIZE < @UART_RAM_END - UART_RAM_START) {
    50                                  !error "UART RAM allocation insufficient. Allocated: ", .UART_RAM_SIZE, " Require: ", (@UART_RAM_END - UART_RAM_START)
    51                          }
    52                          
    53                          
    54                          ; IO Ports
    55                          UART_REG      = IO_PORT_BASE_ADDRESS | UART_IO_PORT
    56                          UART_DATA     = IO_PORT_BASE_ADDRESS | UART_IO_PORT | $01
    57                          
    58                          ; -----------------------------------------------------------------------------
    59                          ; Constants
    60                          ; -----------------------------------------------------------------------------
    61                          UART_CTL_MASTER_RESET       = %00000011
    62                          UART_CTL_CLOCK_DIV_16       = %00000001
    63                          UART_CTL_CLOCK_DIV_64       = %00000010
    64                          UART_CTL_WORD_7BIT_EPB_2SB  = %00000000
    65                          UART_CTL_WORD_7BIT_OPB_2SB  = %00000100
    66                          UART_CTL_WORD_7BIT_EPB_1SB  = %00001000
    67                          UART_CTL_WORD_7BIT_OPB_1SB  = %00001100
    68                          UART_CTL_WORD_8BIT_2SB      = %00010000
    69                          UART_CTL_WORD_8BIT_1SB      = %00010100
    70                          UART_CTL_WORD_8BIT_EPAR_1SB = %00011000
    71                          UART_CTL_WORD_8BIT_OPAR_1SB = %00011100
    72                          UART_CTL_RX_INT_ENABLE      = %10000000
    73                          
    74                          UART_STATUS_RX_REG_FULL     = %00000001
    75                          UART_STATUS_TX_REG_EMPTY    = %00000010
    76                          UART_STATUS_CARRIER_DETECT  = %00000100
    77                          UART_STATUS_CLEAR_TO_SEND   = %00001000
    78                          UART_STATUS_FRAMING_ERROR   = %00010000
    79                          UART_STATUS_RCVR_OVERRUN    = %00100000
    80                          UART_STATUS_PARITY_ERROR    = %01000000
    81                          UART_STATUS_IRQ             = %10000000
    82                          
    83                          UART_FLOWCTRL_XON           = $11
    84                          UART_FLOWCTRL_XOFF          = $13
    85                          
    86                          UART_RX_BUFFER_XOFF_SIZE    = 192
    87                          UART_RX_BUFFER_XON_SIZE     = 4
    88                          
    89                          
    90                          ; -----------------------------------------------------------------------------
    91                          ; uartInit: Initialise the UART
    92                          ; -----------------------------------------------------------------------------
    93                          uartInit:
    94  f1a5 a900                       lda #0
    95  f1a7 852a                       sta UART_RX_BUFFER_HEAD
    96  f1a9 852b                       sta UART_RX_BUFFER_TAIL
    97  f1ab 852c                       sta UART_RX_BUFFER_BYTES
    98  f1ad 852d                       sta UART_RX_FLAGS
    99                          
   100  f1af a903                       lda #UART_CTL_MASTER_RESET
   101  f1b1 8d207f                     sta UART_REG
   102  f1b4 ea                         nop
   103  f1b5 ea                         nop
   104                          
   105  f1b6 a992                       lda #(UART_CTL_CLOCK_DIV_64 | UART_CTL_WORD_8BIT_2SB | UART_CTL_RX_INT_ENABLE)
   106  f1b8 8d207f                     sta UART_REG
   107  f1bb ea                         nop
   108  f1bc ea                         nop
   109                          
   110  f1bd 20e5f1                     jsr uartFlowCtrlXon
   111                          
   112  f1c0 60                         rts
   113                          
   114                          ; -----------------------------------------------------------------------------
   115                          ; uartIrq: Standard UART IRQ handler
   116                          ; -----------------------------------------------------------------------------
   117                          uartIrq:
   118  f1c1 a901                       lda #UART_STATUS_RX_REG_FULL
   119  f1c3 2c207f                     bit UART_REG
   120  f1c6 f01c                       beq @endFlowControlCheck
   121  f1c8 ea                         nop
   122  f1c9 ea                         nop
   123                          
   124  f1ca da                         phx
   125  f1cb a62a                       ldx UART_RX_BUFFER_HEAD
   126  f1cd ad217f                     lda UART_DATA
   127  f1d0 9d827b                     sta UART_RX_BUFFER, x
   128  f1d3 e62a                       inc UART_RX_BUFFER_HEAD
   129  f1d5 e62c                       inc UART_RX_BUFFER_BYTES
   130  f1d7 fa                         plx
   131                          
   132                          @flowControlCheck
   133                                  ; check flow control
   134  f1d8 ff2d09                     bbs7 UART_RX_FLAGS, @endFlowControlCheck    ; if already xoff, just leave
   135  f1db a9c0                       lda #UART_RX_BUFFER_XOFF_SIZE               ; otherwise, should we ask for xoff?
   136  f1dd c52c                       cmp UART_RX_BUFFER_BYTES
   137  f1df b003                       bcs @endFlowControlCheck                    ; all good
   138  f1e1 20f0f1                     jsr uartFlowCtrlXoff                        ; stop please.
   139                          
   140                          @endFlowControlCheck
   141  f1e4 60                         rts
   142                          
   143                          ; -----------------------------------------------------------------------------
   144                          ; uartFlowCtrlXon: Allow client to send data
   145                          ; -----------------------------------------------------------------------------
   146                          uartFlowCtrlXon:
   147  f1e5 772d                       rmb7 UART_RX_FLAGS        
   148  f1e7 a911                       lda #UART_FLOWCTRL_XON
   149  f1e9 ea                         nop
   150  f1ea ea                         nop
   151  f1eb ea                         nop
   152  f1ec ea                         nop
   153  f1ed 4c26f2                     jmp uartOut
   154                          
   155                          ; -----------------------------------------------------------------------------
   156                          ; uartFlowCtrlXoff: Stop client to sending data
   157                          ; -----------------------------------------------------------------------------
   158                          uartFlowCtrlXoff
   159  f1f0 f72d                       smb7 UART_RX_FLAGS
   160  f1f2 a913                       lda #UART_FLOWCTRL_XOFF
   161  f1f4 ea                         nop
   162  f1f5 ea                         nop
   163  f1f6 4c2cf2                     jmp uartOutNoBsCheck
   164                          
   165                          ; -----------------------------------------------------------------------------
   166                          ; uartInWait: Input a byte from the UART (wait forever)
   167                          ; -----------------------------------------------------------------------------
   168                          ; Outputs:
   169                          ;   A: Value of the buffer
   170                          ; -----------------------------------------------------------------------------
   171                          uartInWait:
   172  f1f9 a52a                       lda UART_RX_BUFFER_HEAD
   173  f1fb c52b                       cmp UART_RX_BUFFER_TAIL
   174  f1fd f0fa                       beq uartInWait
   175  f1ff 08                         php
   176  f200 78                         sei
   177  f201 8008                       bra .uartIncheckFlowControl
   178                          
   179                          ; -----------------------------------------------------------------------------
   180                          ; uartInNoWait: Input a byte from the UART (don't wait)
   181                          ; -----------------------------------------------------------------------------
   182                          ; Outputs:
   183                          ;   A: Value of the buffer
   184                          ;   C: Set if a byte is read
   185                          ; -----------------------------------------------------------------------------
   186                          uartInNoWait:
   187  f203 08                         php
   188  f204 78                         sei
   189  f205 a52a                       lda UART_RX_BUFFER_HEAD
   190  f207 c52b                       cmp UART_RX_BUFFER_TAIL
   191  f209 f018                       beq @noData
   192                          
   193                          .uartIncheckFlowControl
   194                                  ; check flow control
   195  f20b 7f2d09                     bbr7 UART_RX_FLAGS, @readUartValue  ; if already xon, just exit again
   196  f20e a904                       lda #UART_RX_BUFFER_XON_SIZE        ; otherwise, should we ask for xon?
   197  f210 c52c                       cmp UART_RX_BUFFER_BYTES
   198  f212 9003                       bcc @readUartValue                  ; all good
   199  f214 20e5f1                     jsr uartFlowCtrlXon                 ; continue sending please.
   200                          
   201                          @readUartValue
   202  f217 a62b                       ldx UART_RX_BUFFER_TAIL
   203  f219 bd827b                     lda UART_RX_BUFFER, x
   204  f21c e62b                       inc UART_RX_BUFFER_TAIL
   205  f21e c62c                       dec UART_RX_BUFFER_BYTES
   206  f220 28                         plp
   207  f221 38                         sec
   208  f222 60                         rts
   209                          @noData
   210  f223 28                         plp
   211  f224 18                         clc
   212  f225 60                         rts
   213                          
   214                          
   215                          ; -----------------------------------------------------------------------------
   216                          ; uartOut: Output a byte to the UART
   217                          ; -----------------------------------------------------------------------------
   218                          ; Inputs:
   219                          ;   A: Value to output
   220                          ; -----------------------------------------------------------------------------
   221                          uartOut:
   222  f226 c908                       cmp #$08        ; bs
   223  f228 d002                       bne uartOutNoBsCheck
   224  f22a a97f                       lda #$7f        ; del
   225                          uartOutNoBsCheck:
   226  f22c 48                         pha
   227  f22d a902                       lda #UART_STATUS_TX_REG_EMPTY
   228                          
   229                          @aciaTestSend
   230  f22f 2c207f                     bit UART_REG
   231  f232 ea                         nop
   232  f233 ea                         nop
   233  f234 d002                       bne +
   234  f236 80f7                       bra @aciaTestSend
   235                          
   236                          +
   237  f238 68                         pla
   238  f239 8d217f                     sta UART_DATA
   239  f23c 60                         rts
   240                          
   241                          
   242                          ; -----------------------------------------------------------------------------
   243                          ; uartOutString: Output a string to the UART
   244                          ; -----------------------------------------------------------------------------
   245                          ; Inputs:
   246                          ;   A: Value to output
   247                          ; -----------------------------------------------------------------------------
   248                          uartOutString:
   249  f23d a000                       ldy #0
   250                          -
   251  f23f b134                       lda (STR_ADDR), y
   252  f241 f006                       beq +
   253  f243 202cf2                     jsr uartOutNoBsCheck
   254  f246 c8                         iny
   255  f247 d0f6                       bne -
   256                          +
   257  f249 60                         rts

; ******** Source: kernel.asm
   173                          
   174                          }
   175                          
   176                          !ifndef HBC56_DISABLE_NES {

; ******** Source: ../lib\inp\nes.asm
     1                          ; 6502 NES Controllers - HBC-56
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          
    10                          
    11                          !ifndef NES_IO_PORT { NES_IO_PORT = $82
    12                                  !warn "NES_IO_PORT not provided. Defaulting to ", NES_IO_PORT
    13                          }
    14                          
    15                          !ifndef NES_RAM_START { NES_RAM_START = $7ea1
    16                                  !warn "NES_RAM_START not provided. Defaulting to ", NES_RAM_START
    17                          }
    18                          
    19                          ; -------------------------
    20                          ; High RAM
    21                          ; -------------------------
    22                          NES_TMP        = NES_RAM_START
    23                          NES_RAM_SIZE   = 1
    24                          
    25                          
    26                          !if NES_RAM_END < (NES_RAM_START + NES_RAM_SIZE) {
    27                                  !error "NES_RAM requires ",NES_RAM_SIZE," bytes. Allocated ",NES_RAM_END - NES_RAM_START
    28                          }
    29                          
    30                          
    31                          ; IO Ports
    32                          NES1_IO_ADDR     = IO_PORT_BASE_ADDRESS | NES_IO_PORT
    33                          NES2_IO_ADDR     = IO_PORT_BASE_ADDRESS | NES_IO_PORT | $01
    34                          
    35                          
    36                          NES_RIGHT       = %00000001
    37                          NES_LEFT        = %00000010
    38                          NES_DOWN        = %00000100
    39                          NES_UP          = %00001000
    40                          NES_START       = %00010000
    41                          NES_SELECT      = %00100000
    42                          NES_B           = %01000000
    43                          NES_A           = %10000000
    44                          
    45                          ; -----------------------------------------------------------------------------
    46                          ; nesWaitForPress: Wait for a NES button press (either port)
    47                          ; -----------------------------------------------------------------------------
    48                          nesWaitForPress:
    49  f24a a9ff                       lda #$ff
    50                          @notPressed
    51  f24c cd827f                     cmp NES1_IO_ADDR
    52  f24f d005                       bne @pressed
    53  f251 cd837f                     cmp NES2_IO_ADDR
    54  f254 f0f6                       beq @notPressed
    55                          @pressed
    56  f256 60                         rts
    57                          
    58                          ; -----------------------------------------------------------------------------
    59                          ; nes1Pressed: Is a button pressed?
    60                          ; -----------------------------------------------------------------------------
    61                          ; Inputs:
    62                          ;   A: Button to test
    63                          ; Outputs:
    64                          ;   Carry set if pressed, Carry clear if not
    65                          nes1Pressed:
    66  f257 2c827f                     bit NES1_IO_ADDR
    67  f25a 18                         clc
    68  f25b d001                       bne +
    69  f25d 38                         sec
    70                          +
    71  f25e 60                         rts
    72                          
    73                          ; -----------------------------------------------------------------------------
    74                          ; nes2Pressed: Is a button pressed?
    75                          ; -----------------------------------------------------------------------------
    76                          ; Inputs:
    77                          ;   A: Button to test
    78                          ; Outputs:
    79                          ;   Carry set if pressed, Carry clear if not
    80                          nes2Pressed:
    81  f25f 2c837f                     bit NES2_IO_ADDR
    82  f262 18                         clc
    83  f263 d001                       bne +
    84  f265 38                         sec
    85                          +
    86  f266 60                         rts
    87                          
    88                          
    89                          
    90                          

; ******** Source: kernel.asm
   177                          
   178                          }
   179                          
   180                          !ifndef HBC56_DISABLE_KEYBOARD {

; ******** Source: ../lib\inp\keyboard.asm
     1                          ; 6502 KB Controller - HBC-56
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github@com/visrealm/hbc-56
     8                          ;
     9                          
    10                          !ifndef HAVE_MATH_INC { !src "ut/math.inc" }
    11                          
    12                          HAVE_KEYBOARD = 1
    13                          
    14                          ; -------------------------
    15                          ; Constants
    16                          ; -------------------------
    17                          !ifndef KB_IO_PORT { KB_IO_PORT = $80
    18                                  !warn "KB_IO_PORT not provided@ Defaulting to ", KB_IO_PORT
    19                          }
    20                          
    21                          !ifndef KB_RAM_START { KB_RAM_START = $7ea1
    22                                  !warn "KB_RAM_START not provided@ Defaulting to ", KB_RAM_START
    23                          }
    24                          
    25                          ; -------------------------
    26                          ; High RAM
    27                          ; -------------------------
    28                          KB_FLAGS          = KB_RAM_START
    29                          KB_TMP_X          = KB_RAM_START + 1
    30                          KB_TMP_Y          = KB_RAM_START + 2
    31                          KB_CB_PRESSED     = KB_RAM_START + 3
    32                          KB_CB_RELEASED    = KB_RAM_START + 5
    33                          KB_CURRENT_STATE  = KB_RAM_START + 7
    34                          KB_BUFFER_HEAD    = KB_RAM_START + 8         ; head of circular buffer
    35                          KB_BUFFER_TAIL    = KB_RAM_START + 9         ; tail of circular buffer
    36                          KB_BUFFER         = KB_RAM_START + 10
    37                          KB_BUFFER_SIZE    = (1 << 4)
    38                          KB_BUFFER_MASK    = KB_BUFFER_SIZE - 1
    39                          KB_PRESSED_MAP    = KB_BUFFER + KB_BUFFER_SIZE
    40                          
    41                          KB_PRESSED_MAP_SIZE = $fd + 1
    42                          KB_PRESSED_MAP_BYTES = 32
    43                          
    44                          KB_RAM_SIZE     = (KB_PRESSED_MAP + KB_PRESSED_MAP_BYTES) - KB_RAM_START
    45                          
    46                          
    47                          !if KB_RAM_END < (KB_RAM_START + KB_RAM_SIZE) {
    48                                  !error "KB_RAM requires ",KB_RAM_SIZE," bytes@ Allocated ",KB_RAM_END - KB_RAM_START
    49                          }
    50                          
    51                          ; -------------------------
    52                          ; Contants
    53                          ; -------------------------
    54                          KB_SHIFT_DOWN   = %00000001
    55                          KB_CTRL_DOWN    = %00000010
    56                          KB_ALT_DOWN     = %00000100
    57                          KB_CAPS_LOCK    = %00001000
    58                          KB_NUM_LOCK     = %00010000
    59                          
    60                          KB_RELEASE      = $f0
    61                          KB_EXT_KEY      = $e0
    62                          KB_PAUSE_KEY    = $e1
    63                          
    64                          KB_SCANCODE_0 = $45
    65                          KB_SCANCODE_1 = $16
    66                          KB_SCANCODE_2 = $1E
    67                          KB_SCANCODE_3 = $26
    68                          KB_SCANCODE_4 = $25
    69                          KB_SCANCODE_5 = $2E
    70                          KB_SCANCODE_6 = $36
    71                          KB_SCANCODE_7 = $3D
    72                          KB_SCANCODE_8 = $3E
    73                          KB_SCANCODE_9 = $46
    74                          KB_SCANCODE_A = $1C
    75                          KB_SCANCODE_B = $32
    76                          KB_SCANCODE_C = $21
    77                          KB_SCANCODE_D = $23
    78                          KB_SCANCODE_E = $24
    79                          KB_SCANCODE_F = $2B
    80                          KB_SCANCODE_G = $34
    81                          KB_SCANCODE_H = $33
    82                          KB_SCANCODE_I = $43
    83                          KB_SCANCODE_J = $3B
    84                          KB_SCANCODE_K = $42
    85                          KB_SCANCODE_L = $4B
    86                          KB_SCANCODE_M = $3A
    87                          KB_SCANCODE_N = $31
    88                          KB_SCANCODE_O = $44
    89                          KB_SCANCODE_P = $4D
    90                          KB_SCANCODE_Q = $15
    91                          KB_SCANCODE_R = $2D
    92                          KB_SCANCODE_S = $1B
    93                          KB_SCANCODE_T = $2C
    94                          KB_SCANCODE_U = $3C
    95                          KB_SCANCODE_V = $2A
    96                          KB_SCANCODE_W = $1D
    97                          KB_SCANCODE_X = $22
    98                          KB_SCANCODE_Y = $35
    99                          KB_SCANCODE_Z = $1A
   100                          KB_SCANCODE_F1 = $05
   101                          KB_SCANCODE_F2 = $06
   102                          KB_SCANCODE_F3 = $04
   103                          KB_SCANCODE_F4 = $0C
   104                          KB_SCANCODE_F5 = $03
   105                          KB_SCANCODE_F6 = $0B
   106                          KB_SCANCODE_F7 = $83
   107                          KB_SCANCODE_F8 = $0A
   108                          KB_SCANCODE_F9 = $01
   109                          KB_SCANCODE_F10 = $09
   110                          KB_SCANCODE_F11 = $78
   111                          KB_SCANCODE_F12 = $07
   112                          KB_SCANCODE_NUMPAD_0 = $70
   113                          KB_SCANCODE_NUMPAD_1 = $69
   114                          KB_SCANCODE_NUMPAD_2 = $72
   115                          KB_SCANCODE_NUMPAD_3 = $7A
   116                          KB_SCANCODE_NUMPAD_4 = $6B
   117                          KB_SCANCODE_NUMPAD_5 = $73
   118                          KB_SCANCODE_NUMPAD_6 = $74
   119                          KB_SCANCODE_NUMPAD_7 = $6C
   120                          KB_SCANCODE_NUMPAD_8 = $75
   121                          KB_SCANCODE_NUMPAD_9 = $7D
   122                          KB_SCANCODE_NUMPAD_DIVIDE = $CA
   123                          KB_SCANCODE_NUMPAD_ENTER = $DA
   124                          KB_SCANCODE_NUMPAD_MINUS = $7B
   125                          KB_SCANCODE_NUMPAD_MULTIPLY = $7C
   126                          KB_SCANCODE_NUMPAD_PERIOD = $71
   127                          KB_SCANCODE_NUMPAD_PLUS = $79
   128                          KB_SCANCODE_NUM_LOCK = $77
   129                          KB_SCANCODE_ALT_LEFT = $11
   130                          KB_SCANCODE_ALT_RIGHT_ = $91
   131                          KB_SCANCODE_APOS = $52
   132                          KB_SCANCODE_ARROW_DOWN = $F2
   133                          KB_SCANCODE_ARROW_LEFT = $EB
   134                          KB_SCANCODE_ARROW_RIGHT = $F4
   135                          KB_SCANCODE_ARROW_UP = $F5
   136                          KB_SCANCODE_BACKSPACE = $66
   137                          KB_SCANCODE_CAPS_LOCK = $58
   138                          KB_SCANCODE_COMMA = $41
   139                          KB_SCANCODE_CTRL_LEFT = $14
   140                          KB_SCANCODE_CTRL_RIGHT = $94
   141                          KB_SCANCODE_DELETE = $F1
   142                          KB_SCANCODE_END = $E9
   143                          KB_SCANCODE_ENTER = $5A
   144                          KB_SCANCODE_EQUAL = $55
   145                          KB_SCANCODE_ESC = $76
   146                          KB_SCANCODE_HOME = $EC
   147                          KB_SCANCODE_INSERT = $F0
   148                          KB_SCANCODE_MENU = $AF
   149                          KB_SCANCODE_MINUS = $4E
   150                          KB_SCANCODE_PAGE_DOWN = $FA
   151                          KB_SCANCODE_PAGE_UP = $FD
   152                          KB_SCANCODE_PAUSE = $E1
   153                          KB_SCANCODE_PERIOD = $49
   154                          KB_SCANCODE_PRTSCR = $92
   155                          KB_SCANCODE_SCROLL_LOCK = $7E
   156                          KB_SCANCODE_SEMICOLON = $4C
   157                          KB_SCANCODE_SHIFT_LEFT = $12
   158                          KB_SCANCODE_SHIFT_RIGHT = $59
   159                          KB_SCANCODE_SLASH_BACK = $5D
   160                          KB_SCANCODE_SLASH_FORWARD = $4A
   161                          KB_SCANCODE_SPACEBAR = $29
   162                          KB_SCANCODE_SQUARE_LEFT = $54
   163                          KB_SCANCODE_SQUARE_RIGHT = $5B
   164                          KB_SCANCODE_TAB = $0D
   165                          KB_SCANCODE_TILDE = $0E
   166                          KB_SCANCODE_WINDOWS_LEFT = $9F
   167                          KB_SCANCODE_WINDOWS_RIGHT = $A7
   168                          
   169                          
   170                          KB_SHIFT_LEFT_MAP_BYTE = KB_SCANCODE_SHIFT_LEFT >> 3
   171                          KB_SHIFT_LEFT_MAP_BIT  = $80 >> (KB_SCANCODE_SHIFT_LEFT & $07)
   172                          
   173                          KB_SHIFT_RIGHT_MAP_BYTE = KB_SCANCODE_SHIFT_RIGHT >> 3
   174                          KB_SHIFT_RIGHT_MAP_BIT  = $80 >> (KB_SCANCODE_SHIFT_RIGHT & $07)
   175                          
   176                          
   177                          ; IO Ports
   178                          KB_IO_ADDR         = IO_PORT_BASE_ADDRESS | KB_IO_PORT
   179                          KB_STATUS_ADDR     = IO_PORT_BASE_ADDRESS | KB_IO_PORT | $01
   180                          
   181                          ; -----------------------------------------------------------------------------
   182                          ; kbInit: Initialise the keyboard
   183                          ; -----------------------------------------------------------------------------
   184                          kbInit:
   185  f267 a900                       lda #$00
   186  f269 8d867c                     sta KB_FLAGS
   187                          
   188  f26c a210                       ldx #16 ;buffer size
   189                                  
   190                                  ; ensure the hardware keyboard buffer is clear
   191                          -
   192  f26e 8e877c                     stx KB_TMP_X
   193  f271 2022f3                     jsr .kbReadByte
   194  f274 ae877c                     ldx KB_TMP_X
   195  f277 ca                         dex
   196  f278 d0f4                       bne -
   197                          
   198  f27a a220a900ca9da07c...        +memset KB_PRESSED_MAP, 0, KB_PRESSED_MAP_BYTES
   199                          
   200  f286 9c8e7c                     stz KB_BUFFER_HEAD
   201  f289 9c8f7c                     stz KB_BUFFER_TAIL
   202                          
   203  f28c a900                       lda #.KB_STATE_DEFAULT
   204  f28e 8d8d7c                     sta KB_CURRENT_STATE
   205                          
   206                                  ; flow through
   207                          
   208                          kbResetCallbacks:
   209  f291 a9a1                       lda #<.kbDummyCb
   210  f293 8d897c                     sta KB_CB_PRESSED
   211  f296 8d8b7c                     sta KB_CB_RELEASED
   212                                  
   213  f299 a9f2                       lda #>.kbDummyCb
   214  f29b 8d8a7c                     sta KB_CB_PRESSED + 1
   215  f29e 8d8c7c                     sta KB_CB_RELEASED + 1
   216                          
   217                                  ; flow through
   218                          
   219                          .kbDummyCb:
   220  f2a1 60                         rts
   221                          
   222                          ; -----------------------------------------------------------------------------
   223                          ; kbIntHandler: Standard keyboard interrupt handler
   224                          ; -----------------------------------------------------------------------------
   225                          kbIntHandler:
   226  f2a2 2022f3                     jsr .kbReadByte
   227  f2a5 e000                       cpx #0
   228  f2a7 f0f8                       beq .kbDummyCb
   229                          
   230  f2a9 8a                         txa     ; acc now holds scancode
   231                          
   232  f2aa ae8d7c                     ldx KB_CURRENT_STATE
   233                          
   234  f2ad 7cb0f2                     jmp (.kbStateHandlers, x)
   235                          
   236                          .KB_STATE_DEFAULT          = 0
   237                          .KB_STATE_RELEASE          = 2
   238                          .KB_STATE_EXTENDED         = 4
   239                          .KB_STATE_EXTENDED_RELEASE = 6
   240                          .KB_STATE_PAUSE_SEQ        = 8
   241                          
   242                          .kbStateHandlers:
   243  f2b0 baf2e0f2edf2def2...!word .stdKeyHandler, .relKeyHandler, .extKeyHandler, .extRelKeyHandler, .pauseKeyHandler
   244                          
   245                          ; default scancode handler
   246                          .stdKeyHandler
   247  f2ba c9f0                       cmp #KB_RELEASE
   248  f2bc d006                       bne +
   249  f2be a902                       lda #.KB_STATE_RELEASE
   250  f2c0 8d8d7c                     sta KB_CURRENT_STATE
   251  f2c3 60                         rts
   252                          +
   253  f2c4 c9e0                       cmp #KB_EXT_KEY
   254  f2c6 d006                       bne +
   255  f2c8 a904                       lda #.KB_STATE_EXTENDED
   256  f2ca 8d8d7c                     sta KB_CURRENT_STATE
   257  f2cd 60                         rts
   258                          +
   259  f2ce c9e1                       cmp #KB_PAUSE_KEY
   260  f2d0 d006                       bne +
   261  f2d2 a908                       lda #.KB_STATE_PAUSE_SEQ
   262  f2d4 8d8d7c                     sta KB_CURRENT_STATE
   263  f2d7 60                         rts
   264                          +
   265                                  ; a regular key was pressed 
   266                                  ; TODO: bit field rather than a byte per key?
   267  f2d8 2034f3                     jsr .kbSetKey
   268                          
   269  f2db 6c897c                     jmp (KB_CB_PRESSED)
   270                                  ; subroutine returns above
   271                          
   272                          ; extended release scancode handler
   273                          .extRelKeyHandler:
   274  f2de 0980                       ora #$80
   275                                  ; flow through
   276                          
   277                          ;  release scancode handler
   278                          .relKeyHandler:
   279  f2e0 aa                         tax
   280  f2e1 2069f3                     jsr .kbClearKey
   281                          
   282  f2e4 a900                       lda #.KB_STATE_DEFAULT
   283  f2e6 8d8d7c                     sta KB_CURRENT_STATE
   284  f2e9 8a                         txa
   285                          
   286  f2ea 6c8b7c                     jmp (KB_CB_RELEASED)
   287                          
   288                          ; extended scancode handler
   289                          .extKeyHandler:
   290  f2ed c9f0                       cmp #KB_RELEASE
   291  f2ef d006                       bne +
   292  f2f1 a906                       lda #.KB_STATE_EXTENDED_RELEASE
   293  f2f3 8d8d7c                     sta KB_CURRENT_STATE
   294  f2f6 60                         rts
   295                          +
   296  f2f7 0980                       ora #$80
   297                                  
   298  f2f9 2034f3                     jsr .kbSetKey
   299                          
   300  f2fc a900                       lda #.KB_STATE_DEFAULT
   301  f2fe 8d8d7c                     sta KB_CURRENT_STATE
   302  f301 8a                         txa
   303                          
   304  f302 6c897c                     jmp (KB_CB_PRESSED)
   305                          
   306                          ; pause/break sequence scancode handler
   307                          .pauseKeyHandler:
   308  f305 c977                       cmp #$77
   309  f307 d018                       bne @notLastByte
   310  f309 aa                         tax
   311  f30a ad817d                     lda KB_PRESSED_MAP + KB_SCANCODE_PAUSE
   312  f30d d006                       bne +
   313  f30f 8e817d                     stx KB_PRESSED_MAP + KB_SCANCODE_PAUSE
   314  f312 6c897c                     jmp (KB_CB_PRESSED)
   315                          +
   316  f315 9c817d                     stz KB_PRESSED_MAP + KB_SCANCODE_PAUSE
   317                          
   318  f318 a900                       lda #.KB_STATE_DEFAULT
   319  f31a 8d8d7c                     sta KB_CURRENT_STATE
   320  f31d 8a                         txa
   321                          
   322  f31e 6c8b7c                     jmp (KB_CB_RELEASED)
   323                          
   324                          @notLastByte
   325  f321 60                         rts
   326                          
   327                          ; -----------------------------------------------------------------------------
   328                          ; Outputs:
   329                          ;   A: Value of the KB Status (0 if no key)
   330                          ;   X: PS/2 Scancode byte
   331                          ; -----------------------------------------------------------------------------
   332                          .kbReadByte:        
   333  f322 a200                       ldx #0
   334  f324 a904                       lda #$04
   335  f326 2c817f                     bit KB_STATUS_ADDR
   336  f329 f008                       beq @end
   337                          
   338  f32b a020                       ldy #32         ; TODO: this could probably be smaller
   339                          -
   340  f32d 88                         dey
   341  f32e d0fd                       bne -
   342                          
   343  f330 ae807f                     ldx KB_IO_ADDR
   344                          @end
   345  f333 60                         rts
   346                          
   347                          
   348                          ; -----------------------------------------------------------------------------
   349                          ; .kbSetKey: Set a key is pressed in KB_PRESSED_MAP
   350                          ; Inputs:
   351                          ;    A - scancode
   352                          ; -----------------------------------------------------------------------------
   353                          .kbSetKey:
   354  f334 ae8e7c                     ldx KB_BUFFER_HEAD      ; store at head of buffer
   355  f337 9d907c                     sta KB_BUFFER, x
   356                          
   357  f33a 8d877c                     sta KB_TMP_X            ; find byte in map
   358  f33d 4a4a4a                     +lsr3
   359  f340 aa                         tax
   360  f341 ad877c                     lda KB_TMP_X
   361  f344 2907                       and #$07
   362  f346 a8                         tay
   363  f347 bda07c                     lda KB_PRESSED_MAP, x
   364  f34a 1930e1                     ora tableBitFromLeft, y ; set bit in map byte
   365  f34d 9da07c                     sta KB_PRESSED_MAP, x   ; update map
   366                          
   367                                  ; check for toggle keys
   368  f350 ae877c                     ldx KB_TMP_X
   369  f353 e058                       cpx #KB_SCANCODE_CAPS_LOCK
   370  f355 d008                       bne +
   371  f357 a908                       lda #KB_CAPS_LOCK
   372  f359 4d867c                     eor KB_FLAGS
   373  f35c 8d867c                     sta KB_FLAGS
   374                          +
   375                          
   376  f35f ad8e7c                     lda KB_BUFFER_HEAD      ; increment (and mask) buffer head
   377  f362 1a                         inc
   378  f363 290f                       and #KB_BUFFER_MASK
   379  f365 8d8e7c                     sta KB_BUFFER_HEAD
   380  f368 60                         rts
   381                          
   382                          ; -----------------------------------------------------------------------------
   383                          ; .kbClearKey: Clear a key is pressed in KB_PRESSED_MAP
   384                          ; Inputs:
   385                          ;    A - scancode
   386                          ; -----------------------------------------------------------------------------
   387                          .kbClearKey:
   388  f369 8d877c                     sta KB_TMP_X
   389  f36c 4a4a4a                     +lsr3
   390  f36f aa                         tax
   391  f370 ad877c                     lda KB_TMP_X
   392  f373 2907                       and #$07
   393  f375 a8                         tay
   394  f376 bda07c                     lda KB_PRESSED_MAP, x
   395  f379 3938e1                     and tableInvBitFromLeft, y
   396  f37c 9da07c                     sta KB_PRESSED_MAP, x
   397  f37f 60                         rts
   398                          
   399                          
   400                          ; -----------------------------------------------------------------------------
   401                          ; .kbPopTail: Pop a scancode from the tail of the buffer
   402                          ; Inputs:
   403                          ;    A - scancode
   404                          ; -----------------------------------------------------------------------------
   405                          .kbPopTail:
   406  f380 ad8f7c                     lda KB_BUFFER_TAIL
   407  f383 aa                         tax
   408  f384 1a                         inc
   409  f385 290f                       and #KB_BUFFER_MASK
   410  f387 8d8f7c                     sta KB_BUFFER_TAIL
   411  f38a bd907c                     lda KB_BUFFER, x
   412  f38d 60                         rts
   413                          
   414                          ; -----------------------------------------------------------------------------
   415                          ; kbIsPressed: Is a key pressed right now?
   416                          ; Inputs:
   417                          ;    X - scancode
   418                          ; Returns:
   419                          ;    Z - clear if pressed, set if not pressed
   420                          ; -----------------------------------------------------------------------------
   421                          kbIsPressed:
   422  f38e 08                         php
   423  f38f 78                         sei
   424  f390 8e877c                     stx KB_TMP_X
   425  f393 8a                         txa
   426  f394 4a4a4a                     +lsr3
   427  f397 aa                         tax
   428  f398 ad877c                     lda KB_TMP_X
   429  f39b 2907                       and #$07
   430  f39d a8                         tay
   431  f39e b930e1                     lda tableBitFromLeft, y
   432  f3a1 3da07c                     and KB_PRESSED_MAP, x
   433  f3a4 ae877c                     ldx KB_TMP_X
   434  f3a7 28                         plp
   435  f3a8 c900                       cmp #0
   436  f3aa 60                         rts
   437                          
   438                          
   439                          ; -----------------------------------------------------------------------------
   440                          ; kbWaitForScancode: Wait for a key press
   441                          ; Returns:
   442                          ;    A - scancode
   443                          ; -----------------------------------------------------------------------------
   444                          kbWaitForScancode:
   445  f3ab 08                         php
   446  f3ac 78                         sei        
   447  f3ad 38                         sec
   448  f3ae ad8e7c                     lda KB_BUFFER_HEAD
   449  f3b1 ed8f7c                     sbc KB_BUFFER_TAIL
   450  f3b4 28                         plp
   451  f3b5 c900                       cmp #0
   452  f3b7 f0f2                       beq kbWaitForScancode
   453  f3b9 08                         php
   454  f3ba 78                         sei
   455  f3bb 2080f3                     jsr .kbPopTail
   456  f3be 28                         plp
   457  f3bf 60                         rts
   458                          
   459                          ; -----------------------------------------------------------------------------
   460                          ; kbNextScancode: Return the next scancode in the buffer or zero if empty
   461                          ; Returns:
   462                          ;    A - scancode (or zero)
   463                          ; -----------------------------------------------------------------------------
   464                          kbNextScancode:
   465  f3c0 08                         php
   466  f3c1 78                         sei
   467  f3c2 ad8e7c                     lda KB_BUFFER_HEAD
   468  f3c5 cd8f7c                     cmp KB_BUFFER_TAIL
   469  f3c8 f007                       beq @noScancode
   470  f3ca 2080f3                     jsr .kbPopTail
   471  f3cd 28                         plp
   472  f3ce c900                       cmp #0
   473  f3d0 60                         rts
   474                          
   475                          @noScancode
   476  f3d1 28                         plp
   477  f3d2 a900                       lda #0
   478  f3d4 60                         rts
   479                          
   480                          ; -----------------------------------------------------------------------------
   481                          ; kbScancodeToAscii: Convert a scancode to ascii. shift/caps lock is honoured
   482                          ; Inputs:
   483                          ;    A - scancode (or zero)
   484                          ; Returns:
   485                          ;    A - ascii character
   486                          ;    C - set if valid character in A
   487                          ; -----------------------------------------------------------------------------
   488                          kbScancodeToAscii:
   489  f3d5 da                         phx
   490  f3d6 8d877c                     sta KB_TMP_X
   491  f3d9 18                         clc
   492  f3da 1002                       bpl +
   493  f3dc fa                         plx
   494  f3dd 60                         rts
   495                          +
   496  f3de 08                         php
   497  f3df 78                         sei
   498  f3e0 a202                       ldx #KB_SHIFT_LEFT_MAP_BYTE
   499  f3e2 a920                       lda #KB_SHIFT_LEFT_MAP_BIT
   500  f3e4 3ca07c                     bit KB_PRESSED_MAP, x
   501  f3e7 f003                       beq +
   502  f3e9 38                         sec
   503  f3ea 800a                       bra @doneShiftCheck
   504                          +
   505                          
   506  f3ec a20b                       ldx #KB_SHIFT_RIGHT_MAP_BYTE
   507  f3ee a940                       lda #KB_SHIFT_RIGHT_MAP_BIT
   508  f3f0 3ca07c                     bit KB_PRESSED_MAP, x
   509  f3f3 f001                       beq +
   510  f3f5 38                         sec
   511                          +
   512                          
   513                          @doneShiftCheck:
   514  f3f6 b008                       bcs @shiftedKeys:
   515  f3f8 ae877c                     ldx KB_TMP_X
   516  f3fb bd39f4                     lda KEY_MAP, x
   517  f3fe 8006                       bra @end
   518                          
   519                          @shiftedKeys:
   520  f400 ae877c                     ldx KB_TMP_X
   521  f403 bdb9f4                     lda KEY_MAP_SHIFTED, x
   522                          
   523                          @end
   524  f406 2018e0                     jsr isAlpha
   525  f409 9014                       bcc @afterAlphaCheck
   526  f40b 8d877c                     sta KB_TMP_X
   527  f40e a908                       lda #KB_CAPS_LOCK
   528  f410 2d867c                     and KB_FLAGS
   529  f413 f007                       beq +
   530  f415 ad877c                     lda KB_TMP_X
   531  f418 4920                       eor #$20
   532  f41a 8003                       bra @afterAlphaCheck
   533                          +
   534  f41c ad877c                     lda KB_TMP_X
   535                          @afterAlphaCheck
   536  f41f 28                         plp
   537  f420 fa                         plx
   538  f421 c9ff                       cmp #$ff
   539  f423 38                         sec
   540  f424 d001                       bne +
   541  f426 18                         clc
   542                          +        
   543  f427 60                         rts
   544                          
   545                          ; -----------------------------------------------------------------------------
   546                          ; kbReadAscii: Read an ASCII caharacter from the keyboard queue
   547                          ; Returns:
   548                          ;    A - ascii character
   549                          ;    C - set if valid character in A
   550                          ; -----------------------------------------------------------------------------
   551                          kbReadAscii:
   552  f428 08                         php
   553  f429 78                         sei
   554  f42a da                         phx
   555  f42b 20c0f3                     jsr kbNextScancode
   556  f42e f005                       beq @noKey
   557  f430 fa                         plx
   558  f431 28                         plp
   559  f432 4cd5f3                     jmp kbScancodeToAscii
   560                          @noKey
   561  f435 fa                         plx
   562  f436 28                         plp
   563  f437 18                         clc
   564  f438 60                         rts
   565                          
   566                          
   567                          KEY_MAP:
   568                          ;      0   1   2   3   4   5   6   7   8   9   a   b   c   d   e   f
   569  f439 ffffffffffffffff...!byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$09,$60,$ff; 0
   570  f449 ffffffffff7131ff...!byte $ff,$ff,$ff,$ff,$ff,$71,$31,$ff,$ff,$ff,$7a,$73,$61,$77,$32,$ff; 1
   571  f459 ff637864653433ff...!byte $ff,$63,$78,$64,$65,$34,$33,$ff,$ff,$20,$76,$66,$74,$72,$35,$ff; 2
   572  f469 ff6e6268677936ff...!byte $ff,$6e,$62,$68,$67,$79,$36,$ff,$ff,$ff,$6d,$6a,$75,$37,$38,$ff; 3
   573  f479 ff2c6b696f3039ff...!byte $ff,$2c,$6b,$69,$6f,$30,$39,$ff,$ff,$2e,$2f,$6c,$3b,$70,$2d,$ff; 4
   574  f489 ffff27ff5b3dffff...!byte $ff,$ff,$27,$ff,$5b,$3d,$ff,$ff,$ff,$ff,$0d,$5d,$ff,$5c,$ff,$ff; 5
   575  f499 ffffffffffff08ff...!byte $ff,$ff,$ff,$ff,$ff,$ff,$08,$ff,$ff,$31,$ff,$34,$37,$ff,$ff,$ff; 6
   576  f4a9 30ff323536381bff...!byte $30,$ff,$32,$35,$36,$38,$1b,$ff,$ff,$ff,$33,$2d,$ff,$39,$ff,$ff; 7
   577                          
   578                          KEY_MAP_SHIFTED:
   579                          ;      0   1   2   3   4   5   6   7   8   9   a   b   c   d   e   f
   580  f4b9 ffffffffffffffff...!byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$09,$7e,$ff; 0
   581  f4c9 ffffffffff5121ff...!byte $ff,$ff,$ff,$ff,$ff,$51,$21,$ff,$ff,$ff,$5a,$53,$41,$57,$40,$ff; 1
   582  f4d9 ff435844452423ff...!byte $ff,$43,$58,$44,$45,$24,$23,$ff,$ff,$20,$56,$46,$54,$52,$25,$ff; 2
   583  f4e9 ff4e424847595eff...!byte $ff,$4e,$42,$48,$47,$59,$5e,$ff,$ff,$ff,$4d,$4a,$55,$26,$2a,$ff; 3
   584  f4f9 ff3c4b494f2928ff...!byte $ff,$3c,$4b,$49,$4f,$29,$28,$ff,$ff,$3e,$3f,$4c,$3a,$50,$5f,$ff; 4
   585  f509 ffff22ff7b2bffff...!byte $ff,$ff,$22,$ff,$7b,$2b,$ff,$ff,$ff,$ff,$0d,$7d,$ff,$7c,$ff,$ff; 5
   586  f519 ffffffffffff08ff...!byte $ff,$ff,$ff,$ff,$ff,$ff,$08,$ff,$ff,$31,$ff,$34,$37,$ff,$ff,$ff; 6
   587  f529 30ff323536381bff...!byte $30,$ff,$32,$35,$36,$38,$1b,$ff,$ff,$ff,$33,$2d,$ff,$39,$ff,$ff; 7

; ******** Source: kernel.asm
   181                          
   182                          }
   183                          

; ******** Source: ../lib\io\via.asm
     1                          ; 65(C)22 VIA - HBC-56
     2                          ;
     3                          ; Copyright (c) 2022 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          
    10                          
    11                          !ifndef VIA_IO_PORT { VIA_IO_PORT = $f0
    12                                  !warn "VIA_IO_PORT not provided. Defaulting to ", VIA_IO_PORT
    13                          }
    14                          
    15                          !ifndef VIA_RAM_START { VIA_RAM_START = $7d80
    16                                  !warn "VIA_RAM_START not provided. Defaulting to ", VIA_RAM_START
    17                          }
    18                          
    19                          ; -------------------------
    20                          ; High RAM
    21                          ; -------------------------
    22                          VIA_TMP        = VIA_RAM_START
    23                          VIA_RAM_SIZE   = 1
    24                          
    25                          
    26                          !if VIA_RAM_END < (VIA_RAM_START + VIA_RAM_SIZE) {
    27                                  !error "VIA_RAM requires ",VIA_RAM_SIZE," bytes. Allocated ",VIA_RAM_END - VIA_RAM_START
    28                          }
    29                          
    30                          
    31                          VIA_REG_PORT_B  = $00
    32                          VIA_REG_PORT_A  = $01
    33                          VIA_REG_DDR_B   = $02
    34                          VIA_REG_DDR_A   = $03
    35                          VIA_REG_T1C_L   = $04
    36                          VIA_REG_T1C_H   = $05
    37                          VIA_REG_T1L_L   = $06
    38                          VIA_REG_T1L_H   = $07
    39                          VIA_REG_T2C_L   = $08
    40                          VIA_REG_T2C_H   = $09
    41                          VIA_REG_ACR     = $0b
    42                          VIA_REG_IFR     = $0d
    43                          VIA_REG_IER     = $0e
    44                          
    45                          ; IO Ports
    46                          VIA_IO_ADDR     = IO_PORT_BASE_ADDRESS | VIA_IO_PORT
    47                          
    48                          VIA_IO_ADDR_PORT_B      = VIA_IO_ADDR | VIA_REG_PORT_B
    49                          VIA_IO_ADDR_PORT_A      = VIA_IO_ADDR | VIA_REG_PORT_A
    50                          VIA_IO_ADDR_DDR_B       = VIA_IO_ADDR | VIA_REG_DDR_B
    51                          VIA_IO_ADDR_DDR_A       = VIA_IO_ADDR | VIA_REG_DDR_A
    52                          VIA_IO_ADDR_T1C_L       = VIA_IO_ADDR | VIA_REG_T1C_L
    53                          VIA_IO_ADDR_T1C_H       = VIA_IO_ADDR | VIA_REG_T1C_H
    54                          VIA_IO_ADDR_T1L_L       = VIA_IO_ADDR | VIA_REG_T1L_L
    55                          VIA_IO_ADDR_T1L_H       = VIA_IO_ADDR | VIA_REG_T1L_H
    56                          VIA_IO_ADDR_T2C_L       = VIA_IO_ADDR | VIA_REG_T2C_L
    57                          VIA_IO_ADDR_T2C_H       = VIA_IO_ADDR | VIA_REG_T2C_H
    58                          VIA_IO_ADDR_ACR         = VIA_IO_ADDR | VIA_REG_ACR
    59                          VIA_IO_ADDR_IFR         = VIA_IO_ADDR | VIA_REG_IFR
    60                          VIA_IO_ADDR_IER         = VIA_IO_ADDR | VIA_REG_IER
    61                          
    62                          ; Constants
    63                          VIA_DIR_INPUT   = $00
    64                          VIA_DIR_OUTPUT  = $ff
    65                          
    66                          
    67                          
    68                          viaIntHandler:
    69  f539 6ce57c                     jmp (HBC56_VIA_CALLBACK)

; ******** Source: kernel.asm
   184                          
   185                          
   186  f53c 6769746875622e63...+hbc56Title "github.com/visrealm/hbc-56"
   187                          

; ******** Source: bootscreen.asm
     1                          ; 6502 - HBC-56 - Memory tests
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          ;
    10                          
    11                          ; can be anywhere. we own the place at this stage
    12                          LOGO_BUFFER = $3000     
    13                          
    14                          !ifdef HAVE_TMS9918 {
    15                                  HBC56_BORDER     = TMS_DK_BLUE 
    16                                  HBC56_BACKGROUND = TMS_WHITE
    17                                  HBC56_LOGO       = TMS_DK_BLUE 
    18                                  HBC56_TEXT       = TMS_DK_BLUE
    19                          }
    20                          
    21                          !ifdef HBC56_TITLE_TEXT {
    22                                  HBC56_TITLE     = HBC56_TITLE_TEXT
    23                                  HBC56_TITLE_LEN = HBC56_TITLE_TEXT_LEN
    24                          }
    25                          
    26                          .HBC56_PRESS_ANY_KEY_TEXT:
    27  f557 505245535320414e...        !text "PRESS ANY KEY...",0
    28                          .HBC56_PRESS_ANY_KEY_TEXT_LEN = *-.HBC56_PRESS_ANY_KEY_TEXT-1
    29                          
    30                          .HBC56_PRESS_ANY_NES_TEXT:
    31  f568 5052455353204120...        !text "PRESS A TO BEGIN...",0
    32                          .HBC56_PRESS_ANY_NES_TEXT_LEN = *-.HBC56_PRESS_ANY_NES_TEXT-1
    33                          
    34                          !ifdef HAVE_GRAPHICS_LCD {
    35  f57c eaeaeaeaeaeaeaea...        !align 255, 0
    36                          hbc56FontLcd:
    37  f600 0000000000000000...        !bin "lcd/fonts/c64-alnum.bin"
    38                          hbc56LogoLcd:
    39  f800 07c01f03ffe003ff...        !bin "res/hbc56lcd.bin"
    40                          }
    41                          
    42                          !ifdef HAVE_TMS9918 {
    43                          hbc56LogoInd:
    44  f900 c8c9cacbcccdcecf...        !bin "res/hbc56boot.ind"
    45                          hbc56LogoPatt:
    46  f942 fefefefefefefefe...        !bin "res/hbc56boot.patt"
    47                          hbc56LogoPattEnd:        
    48                          }
    49                          
    50                          hbc56BootScreen:
    51                          
    52                          !ifdef HAVE_TMS9918 {
    53  faba 0878a9108d117f20...        +tmsSetAddrColorTable 16
    54  facd a94f                       +tmsColorFgBg HBC56_LOGO, HBC56_BACKGROUND
    55  facf a202                       ldx #2
    56  fad1 20b2e6                     jsr _tmsSendX8
    57  fad4 a94f                       +tmsColorFgBg HBC56_TEXT, HBC56_BACKGROUND
    58  fad6 a210                       ldx #16
    59  fad8 2056e7                     jsr tmsInitColorTable
    60                          
    61  fadb 0878a9a58d117f20...        +tmsSetPosWrite 5,5
    62  faee a9008524a9f98525...        +tmsSendData hbc56LogoInd, 22
    63  fafb 0878a9c58d117f20...        +tmsSetPosWrite 5,6
    64  fb0e a9168524a9f98525...        +tmsSendData hbc56LogoInd + 22, 22
    65  fb1b 0878a9e58d117f20...        +tmsSetPosWrite 5,7
    66  fb2e a92c8524a9f98525...        +tmsSendData hbc56LogoInd + 44, 22
    67                          
    68  fb3b 0878a9408d117f20...        +tmsSetAddrPattTable 200
    69  fb4e a9428524a9f98525...        +tmsSendData hbc56LogoPatt, $178
    70                          
    71  fb64 0878a9c88d117f20...        +tmsPrintZ HBC56_META_TITLE, 8, 14
    72                          
    73                          
    74                                  !ifdef HBC56_TITLE_TEXT {
    75  fb82 0878a9c38d117f20...                +tmsPrintZ HBC56_TITLE, (32 - HBC56_TITLE_LEN) / 2, 22
    76                                  }
    77                          
    78  fba0 a9e4                       +tmsColorFgBg TMS_GREY, HBC56_BORDER
    79  fba2 20cfe5                     jsr tmsSetBackground
    80                          }
    81                          
    82                          !ifdef HAVE_LCD {
    83  fba5 20bfed                     jsr lcdDetect
    84  fba8 907f                       bcc @noLcd
    85                                  !ifdef HAVE_GRAPHICS_LCD {
    86  fbaa 20aaec                             jsr lcdGraphicsMode
    87  fbad a900852ea930852f...                +memset LOGO_BUFFER, $00, 1024
    88  fbc2 a200bd00f89d8030...                +memcpy LOGO_BUFFER + 128, hbc56LogoLcd, 256
    89  fbcf a930                               lda #>LOGO_BUFFER
    90  fbd1 8520                               sta BITMAP_ADDR_H
    91  fbd3 20e7ec                             jsr lcdImage
    92                          
    93  fbd6 a280a900ca9d0030...                +memset LOGO_BUFFER, $0, 128
    94  fbe2 a9008518a97b8519...                +tilemapCreateDefault (TILEMAP_SIZE_X_16 | TILEMAP_SIZE_Y_8), hbc56FontLcd-(32*8)
    95  fc0b a280a920ca9d007a...                +memset TILEMAP_DEFAULT_BUFFER_ADDRESS, ' ', 128
    96                          
    97  fc17 a200bdd07c9d407a...                +memcpy TILEMAP_DEFAULT_BUFFER_ADDRESS + 16*4, HBC56_META_TITLE, 16
    98                          
    99  fc24 a004                               ldy #4
   100  fc26 20ecf0                             jsr tilemapRenderRowToLcd
   101                          
   102                                  } else {
   103                                          !if LCD_ROWS > 2 { +lcdPrint "\n" }
   104                                          !if LCD_COLUMNS > 16 { +lcdPrint "  " }
   105                                          +lcdPrint "     HBC-56\n"
   106                                          !if LCD_COLUMNS > 16 { +lcdPrint "  " }
   107                                          lda #<HBC56_META_TITLE
   108                                          sta STR_ADDR_L
   109                                          lda #>HBC56_META_TITLE
   110                                          sta STR_ADDR_H
   111                                          !if LCD_ROWS = 2 {
   112                                                  jsr lcdLineTwo
   113                                          }                
   114                                          jsr lcdPrint
   115                                          !if LCD_ROWS = 2 {
   116                                                  jsr lcdLineTwo
   117                                          } else {
   118                                                  jsr lcdLineThree
   119                                          }                
   120                                          !if LCD_COLUMNS > 16 { +lcdConsolePrint "  " }
   121                                  }
   122                          @noLcd:
   123                          }
   124  fc29 60                         rts

; ******** Source: kernel.asm
   188                          

; ******** Source: kernel.inc
     1                          ; 6502 - HBC-56 Kernel Macros
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          ;
    10                          
    11                          !macro setIntHandler .address {
    12                                  lda #<.address
    13                                  sta HBC56_INT_VECTOR + 1
    14                                  lda #>.address
    15                                  sta HBC56_INT_VECTOR + 2
    16                                  lda #JMP_OPCODE
    17                                  sta HBC56_INT_VECTOR
    18                          }
    19                          
    20                          !macro setNmiHandler .address {
    21                                  lda #<.address
    22                                  sta HBC56_NMI_VECTOR + 1
    23                                  lda #>.address
    24                                  sta HBC56_NMI_VECTOR + 2
    25                                  lda #JMP_OPCODE
    26                                  sta HBC56_NMI_VECTOR
    27                          }
    28                          
    29                          !macro setHbcMetaNES {
    30                                  lda #HBC56_CONSOLE_FLAG_NES
    31                                  ora HBC56_CONSOLE_FLAGS
    32                                  sta HBC56_CONSOLE_FLAGS
    33                          }
    34                          
    35                          !macro setHbcMetaNoWait {
    36                                  lda #HBC56_CONSOLE_FLAG_NOWAIT
    37                                  ora HBC56_CONSOLE_FLAGS
    38                                  sta HBC56_CONSOLE_FLAGS
    39                          }
    40                          
    41                          
    42                          !macro hbc56SetVsyncCallback .vsync {
    43                                  lda #<.vsync
    44                                  sta HBC56_VSYNC_CALLBACK
    45                                  lda #>.vsync
    46                                  sta HBC56_VSYNC_CALLBACK + 1
    47                          }
    48                          
    49                          !macro hbc56SetViaCallback .cb {
    50                                  lda #<.cb
    51                                  sta HBC56_VIA_CALLBACK
    52                                  lda #>.cb
    53                                  sta HBC56_VIA_CALLBACK + 1
    54                          }
    55                          
    56                          
    57                          !macro setHbcMetaTitle .titleStr {
    58                                  jmp .hbcMetaTitleOut
    59                          .titleStrLabel:
    60                                  !text .titleStr
    61                          .titleStrLabelLen = * - .titleStrLabel
    62                                  !byte 0 ; nul terminator for game name
    63                          
    64                          !if .titleStrLabelLen > HBC56_META_TITLE_MAX_LEN {
    65                                  !error "setHbcMetaTitle: Title metadata limited to ",HBC56_META_TITLE_MAX_LEN,"bytes"
    66                          }
    67                          .hbcMetaTitleOut:
    68                                  +memcpy HBC56_META_TITLE + (HBC56_META_TITLE_MAX_LEN-.titleStrLabelLen)/2, .titleStrLabel, .titleStrLabelLen
    69                                  lda #.titleStrLabelLen
    70                                  sta HBC56_META_TITLE_LEN
    71                          }
    72                          
    73                          !macro consoleEnableCursor {
    74                                  lda HBC56_CONSOLE_FLAGS
    75                                  ora #HBC56_CONSOLE_FLAG_CURSOR
    76                                  sta HBC56_CONSOLE_FLAGS
    77                          }
    78                          
    79                          !macro consoleDisableCursor {
    80                                  lda HBC56_CONSOLE_FLAGS
    81                                  and #!HBC56_CONSOLE_FLAG_CURSOR & $ff
    82                                  sta HBC56_CONSOLE_FLAGS
    83                          }
    84                          
    85                          !macro consoleLCDMode {
    86                                  lda HBC56_CONSOLE_FLAGS
    87                                  ora #HBC56_CONSOLE_FLAG_LCD
    88                                  sta HBC56_CONSOLE_FLAGS
    89                          }
    90                          
    91                          !macro setBreakpoint {
    92                                 !byte $db 
    93                          }
    94                          
    95                          !macro hbc56CustomDelay .delay {
    96                                  ldy #.delay
    97                                  jsr hbc56CustomDelay
    98                          }
    99                          
   100                          !macro hbc56DelayUs .us {
   101                          !if .us = 1 {
   102                                  nop
   103                                  nop
   104                          }
   105                          }
   106                          !macro hbc56DelayMs .ms {
   107                                  lda #<.ms
   108                                  sta DELAY_L
   109                                  lda #>.ms
   110                                  sta DELAY_H
   111                          
   112                                  jsr hbc56CustomDelayMs

; ******** Source: kernel.asm
   189                          

; ******** Source: interrupts.asm
     1                          ; 6502 - HBC-56 Kernel Interrupt Handling
     2                          ;
     3                          ; Copyright (c) 2021 Troy Schrapel
     4                          ;
     5                          ; This code is licensed under the MIT license
     6                          ;
     7                          ; https://github.com/visrealm/hbc-56
     8                          ;
     9                          ;
    10                          
    11                          ; -------------------------
    12                          ; Interrupts
    13                          ; -------------------------
    14                          TMS9918_IRQ            = 1      ; /INT
    15                          KB_IRQ                 = 2      ; RES1
    16                          UART_IRQ               = 3      ; RES2
    17                          VIA_IRQ                = 5      ; Onboard
    18                          
    19                          TMS9918_IRQ_BIT = (1 << (TMS9918_IRQ - 1))
    20                          KB_IRQ_BIT      = (1 << (KB_IRQ - 1))
    21                          UART_IRQ_BIT    = (1 << (UART_IRQ - 1))
    22                          VIA_IRQ_BIT     = (1 << (VIA_IRQ - 1))
    23                          
    24                          INT_CTRL_ADDRESS    = IO_PORT_BASE_ADDRESS | INT_IO_PORT
    25                          
    26                          ; -----------------------------------------------------------------------------
    27                          ; HBC-56 Interrupt handler
    28                          ; -----------------------------------------------------------------------------
    29                          hbc56IntHandler:
    30  fc2a 48                         pha
    31  fc2b da                         phx
    32  fc2c 5a                         phy
    33                          
    34  fc2d addf7f                     lda INT_CTRL_ADDRESS
    35                          
    36                          !ifdef HAVE_UART {
    37  fc30 8904                       bit #UART_IRQ_BIT
    38  fc32 f005                       beq +
    39  fc34 20c1f1                     jsr uartIrq        
    40  fc37 801e                       bra @endIntHandler
    41                          +
    42                          }
    43                          
    44                          !ifdef HAVE_TMS9918 {
    45  fc39 8901                       bit #TMS9918_IRQ_BIT
    46  fc3b f008                       beq +
    47  fc3d 205bfc                     jsr hbc56Tms9918Int
    48  fc40 2c117f                     +tmsReadStatus
    49  fc43 8012                       bra @endIntHandler
    50                          +
    51                          }
    52                          
    53  fc45 8910                       bit #VIA_IRQ_BIT
    54  fc47 f005                       beq +
    55  fc49 2039f5                     jsr viaIntHandler
    56  fc4c 8009                       bra @endIntHandler
    57                          +
    58                          
    59                          !ifdef HAVE_KEYBOARD {
    60  fc4e 8902                       bit #KB_IRQ_BIT
    61  fc50 f005                       beq +
    62  fc52 20a2f2                     jsr kbIntHandler
    63  fc55 8000                       bra @endIntHandler
    64                          +
    65                          }
    66                                  
    67                          @endIntHandler:
    68  fc57 7a                         ply
    69  fc58 fa                         plx
    70  fc59 68                         pla      
    71  fc5a 40                         rti
    72                          
    73                          
    74                          
    75                          ; -----------------------------------------------------------------------------
    76                          ; HBC-56 TMS9918 VSYNC Interrupt handler
    77                          ; -----------------------------------------------------------------------------
    78                          !ifdef HAVE_TMS9918 {
    79                          hbc56Tms9918Int:
    80                          
    81                                  ; update ticks and seconds
    82  fc5b eec97c                     inc HBC56_TICKS
    83  fc5e adc97c                     lda HBC56_TICKS
    84  fc61 c93c                       cmp #TMS_FPS
    85  fc63 d00d                       bne +
    86  fc65 a900                       lda #0
    87  fc67 8dc97c                     sta HBC56_TICKS
    88  fc6a eeca7cd003eecb7c           +inc16 HBC56_SECONDS_L
    89                          +
    90                                  ; "tick" for sfx manager
    91                                  !ifdef HAVE_SFX_MAN {
    92                                          jsr sfxManTick
    93                                  }
    94                          
    95                                  ; handle console if enabled
    96  fc72 2ccd7c                     bit HBC56_CONSOLE_FLAGS
    97  fc75 1003                       bpl +
    98  fc77 207dfc                     jsr .consoleVsyncCallback
    99                          +
   100                          
   101                                  ; rely on callback rts to return
   102  fc7a 6ce37c                     jmp (HBC56_VSYNC_CALLBACK)
   103                          
   104                          
   105                          ; -----------------------------------------------------------------------------
   106                          ; HBC-56 TMS9918 Console update
   107                          ; -----------------------------------------------------------------------------
   108                          .consoleVsyncCallback:
   109                          
   110  fc7d adc97c                     lda HBC56_TICKS
   111  fc80 f007                       beq .doCursor
   112  fc82 c91e                       cmp #30
   113  fc84 f003                       beq .doCursor
   114  fc86 4cb0fc                     jmp @endConsoleCallback
   115                          
   116                          .doCursor:
   117  fc89 8ece7c                     stx HBC56_TMP_X
   118  fc8c 8ccf7c                     sty HBC56_TMP_Y
   119  fc8f 20e7e8                     jsr tmsSetPosConsole
   120  fc92 aece7c                     ldx HBC56_TMP_X
   121  fc95 accf7c                     ldy HBC56_TMP_Y
   122  fc98 adc97c                     lda HBC56_TICKS
   123  fc9b f00b                       beq +
   124  fc9d a920                       lda #' '
   125  fc9f 8d107f2079e5               +tmsPut
   126  fca5 4cb0fc                     jmp @endConsoleCallback
   127                          + 
   128  fca8 a97f                       lda #$7f
   129  fcaa 8d107f2079e5               +tmsPut
   130                          
   131                          @endConsoleCallback
   132                          
   133                          .nullCallbackFunction:
   134  fcb0 60                         rts
   135                          }

; ******** Source: kernel.asm
   190                          
   191                          
   192                          ; -----------------------------------------------------------------------------
   193                          ; HBC-56 Main entry point (reset vector)
   194                          ; -----------------------------------------------------------------------------
   195                          kernelMain:
   196  fcb1 78                         sei
   197  fcb2 d8                         cld     ; make sure we're not in decimal mode
   198  fcb3 a2ff                       ldx #$ff
   199  fcb5 9a                         txs
   200                                  
   201  fcb6 a940                       lda #RTI_OPCODE
   202  fcb8 8d007e                     sta HBC56_INT_VECTOR
   203  fcbb 8d047e                     sta HBC56_NMI_VECTOR
   204                          
   205  fcbe a210a920ca9dd07c...        +memset HBC56_META_TITLE, ' ', HBC56_META_TITLE_MAX_LEN
   206                          
   207  fcca a900                       lda #0
   208  fccc 8dc97c                     sta HBC56_TICKS
   209  fccf 8dca7c                     sta HBC56_SECONDS_L
   210  fcd2 8dcb7c                     sta HBC56_SECONDS_H
   211  fcd5 8dcd7c                     sta HBC56_CONSOLE_FLAGS
   212                          
   213  fcd8 8de07c                     sta HBC56_META_TITLE + HBC56_META_TITLE_MAX_LEN
   214                          
   215                          
   216  fcdb 20fcdf                     jsr HBC56_META_VECTOR   ; user program metadata
   217                          
   218                                  !ifdef HAVE_KEYBOARD {
   219  fcde 2067f2                             jsr kbInit
   220                                  }
   221                          
   222                                  !ifdef HAVE_AY3891X {
   223  fce1 2058e1                             jsr ayInit
   224                                  }
   225                          
   226                                  !ifdef HAVE_SFXMAN {
   227                                          jsr sfxManInit  ; requires TMS interrupts
   228                                  }
   229                          
   230                                  !ifdef HAVE_TMS9918 {
   231  fce4 2065e6                             jsr tmsInit
   232                          
   233  fce7 a94020efe5                         +tmsDisableOutput
   234                          
   235                                          ; dummy callback
   236  fcec a9b08de37ca9fc8d...                +hbc56SetVsyncCallback .nullCallbackFunction
   237                                  }
   238                          
   239  fcf6 a9b08de57ca9fc8d...        +hbc56SetViaCallback .nullCallbackFunction
   240                          
   241                                  !ifdef HAVE_LCD {
   242  fd00 20bfed                             jsr lcdDetect
   243  fd03 900c                               bcc @noLcd1                
   244  fd05 206eed                             jsr lcdInit
   245  fd08 20e1ff                             jsr hbc56Delay
   246  fd0b 2092ed                             jsr lcdDisplayOn
   247  fd0e 20e1ff                             jsr hbc56Delay
   248                          @noLcd1:
   249                                  }
   250                          
   251  fd11 20bafa                     jsr hbc56BootScreen
   252                          
   253  fd14 a92a8d017ea9fc8d...        +setIntHandler hbc56IntHandler
   254                          
   255                                  !ifdef HAVE_TMS9918 {
   256  fd23 a94020e5e5                         +tmsEnableOutput
   257  fd28 a92020efe5                         +tmsDisableInterrupts
   258                                  }
   259                          
   260  fd2d a914                       lda #20
   261  fd2f 8dcc7c                     sta HBC56_TMP
   262                          -
   263  fd32 20e1ff                     jsr hbc56Delay
   264  fd35 cecc7c                     dec HBC56_TMP
   265  fd38 d0f8                       bne -
   266                                 
   267                                  !ifdef HAVE_TMS9918 {
   268  fd3a a92020e5e5                         +tmsEnableInterrupts
   269                                  }
   270  fd3f 58                         cli
   271                          
   272  fd40 20e5fd                     jsr hbc56HighBell
   273                          
   274  fd43 a910                       lda #HBC56_CONSOLE_FLAG_NOWAIT
   275  fd45 2ccd7c                     bit HBC56_CONSOLE_FLAGS
   276  fd48 d07e                       bne .afterInput
   277                          
   278  fd4a a940                       lda #HBC56_CONSOLE_FLAG_NES
   279  fd4c 2dcd7c                     and HBC56_CONSOLE_FLAGS
   280  fd4f f03d                       beq .keyboardInput
   281                          
   282                          
   283                                  ; NES input
   284  fd51 78                         sei
   285                                  !ifdef HAVE_TMS9918 {
   286  fd52 0878a9268d117f20...                +tmsPrintZ .HBC56_PRESS_ANY_NES_TEXT, (32 - .HBC56_PRESS_ANY_NES_TEXT_LEN) / 2, 17
   287                                  }
   288                          
   289                                  !ifdef HAVE_LCD {
   290  fd70 20bfed                             jsr lcdDetect
   291  fd73 9012                               bcc @noLcd2
   292                                          !ifdef HAVE_GRAPHICS_LCD {
   293  fd75 a200bd68f59d607a...                        +memcpy TILEMAP_DEFAULT_BUFFER_ADDRESS + 16*6, .HBC56_PRESS_ANY_NES_TEXT, 16
   294  fd82 a006                                       ldy #6
   295  fd84 20ecf0                                     jsr tilemapRenderRowToLcd
   296                                          } else {
   297                                                  lda #<.HBC56_PRESS_ANY_NES_TEXT
   298                                                  sta STR_ADDR_L
   299                                                  lda #>.HBC56_PRESS_ANY_NES_TEXT
   300                                                  sta STR_ADDR_H
   301                                                  jsr lcdPrint
   302                                          }
   303                          @noLcd2:
   304                                  }
   305  fd87 58                         cli
   306  fd88 204af2                     jsr nesWaitForPress
   307  fd8b 4cc8fd                     jmp .afterInput
   308                          
   309                          .keyboardInput
   310                          !ifdef HAVE_KEYBOARD {
   311                                  ; Keyboard  input
   312  fd8e 78                         sei
   313                                  !ifdef HAVE_TMS9918 {
   314  fd8f 0878a9288d117f20...                +tmsPrintZ .HBC56_PRESS_ANY_KEY_TEXT, (32 - .HBC56_PRESS_ANY_KEY_TEXT_LEN) / 2, 17
   315                                  }
   316                          
   317                                  !ifdef HAVE_LCD {
   318  fdad 20bfed                             jsr lcdDetect
   319  fdb0 9012                               bcc @noLcd3
   320                                          !ifdef HAVE_GRAPHICS_LCD {
   321  fdb2 a200bd57f59d607a...                        +memcpy TILEMAP_DEFAULT_BUFFER_ADDRESS + 16*6, .HBC56_PRESS_ANY_KEY_TEXT, 16
   322  fdbf a006                                       ldy #6
   323  fdc1 20ecf0                                     jsr tilemapRenderRowToLcd
   324                                          } else {
   325                                                  lda #<.HBC56_PRESS_ANY_KEY_TEXT
   326                                                  sta STR_ADDR_L
   327                                                  lda #>.HBC56_PRESS_ANY_KEY_TEXT
   328                                                  sta STR_ADDR_H
   329                                                  jsr lcdPrint        
   330                                          }
   331                          @noLcd3:
   332                                  }
   333  fdc4 58                         cli
   334  fdc5 20abf3                     jsr kbWaitForScancode
   335                          }
   336                          
   337                          .afterInput
   338                          
   339                                  !ifdef HAVE_LCD {
   340                                          ;jsr lcdDetect
   341                                          ;bcc @noLcd4
   342  fdc8 206eed                             jsr lcdInit
   343                                          !ifdef HAVE_GRAPHICS_LCD {
   344  fdcb 20bbec                                     jsr lcdTextMode
   345                                          }
   346  fdce 2080ed                             jsr lcdClear
   347  fdd1 2089ed                             jsr lcdHome
   348                          @noLcd4:
   349                                  }
   350                          
   351                                  !ifdef HAVE_TMS9918 {
   352  fdd4 2039e7                             jsr tmsInitTextTable ; clear output
   353  fdd7 a94020efe5                         +tmsDisableOutput
   354  fddc a92020efe5                         +tmsDisableInterrupts
   355                                  }
   356                                  ; no interrupts until the user code says so
   357  fde1 78                         sei
   358                          
   359  fde2 200080                     jsr DEFAULT_HBC56_RST_VECTOR
   360                          
   361                          ; -----------------------------------------------------------------------------
   362                          ; Beep (higher tone)
   363                          ; -----------------------------------------------------------------------------
   364                          hbc56HighBell:
   365                                  !ifdef HAVE_AY3891X {
   366  fde5 a9078d407fad427f...                +ayToneEnable AY_PSG0, AY_CHC
   367  fdf7 a90a8d407fa90f8d...                +aySetVolume AY_PSG0, AY_CHC, $ff
   368  fe01 a9048d407fa9598d...                +ayPlayNote AY_PSG0, AY_CHC, NOTE_FREQ_F5
   369                                  }
   370  fe15 8032                       bra .noteTimeout
   371                          
   372                          ; -----------------------------------------------------------------------------
   373                          ; Beep (lower tone)
   374                          ; -----------------------------------------------------------------------------
   375                          hbc56Bell:
   376                                  !ifdef HAVE_AY3891X {
   377  fe17 a9078d407fad427f...                +ayToneEnable AY_PSG0, AY_CHC
   378  fe29 a90a8d407fa90f8d...                +aySetVolume AY_PSG0, AY_CHC, $ff
   379  fe33 a9048d407fa97b8d...                +ayPlayNote AY_PSG0, AY_CHC, NOTE_FREQ_E3
   380                                  }
   381  fe47 8000                       bra .noteTimeout
   382                          
   383                          .noteTimeout
   384                                  !ifdef HAVE_SFXMAN {
   385                                          lda HBC56_CONSOLE_FLAGS
   386                                          and #HBC56_CONSOLE_FLAG_LCD
   387                                          bne @skipSfxMan
   388                                          +sfxManSetChannelTimeout  AY_PSG0, AY_CHC, 0.16
   389                                          rts
   390                                  }
   391                          @skipSfxMan
   392                                  !ifdef HAVE_AY3891X {
   393  fe49 20e1ff                             jsr hbc56Delay
   394  fe4c 20e1ff                             jsr hbc56Delay
   395  fe4f a9048d407fa9008d...                +ayStop AY_PSG0, AY_CHC
   396                                  }
   397                          
   398  fe63 60                         rts
   399                          
   400                          ; -----------------------------------------------------------------------------
   401                          ; Software reset
   402                          ; -----------------------------------------------------------------------------
   403                          hbc56Reset:
   404  fe64 4cb1fc                     jmp kernelMain
   405                          
   406                          ; -----------------------------------------------------------------------------
   407                          ; Stop (loop forever)
   408                          ; -----------------------------------------------------------------------------
   409                          hbc56Stop:
   410  fe67 cb                         wai
   411  fe68 4c67fe                     jmp hbc56Stop
   412                          
   413                          ; -----------------------------------------------------------------------------
   414                          ; Delay function
   415                          ; -----------------------------------------------------------------------------
   416                          hbc56CustomDelayMs:
   417  fe6b e637                       inc DELAY_H
   418                          -
   419  fe6d a003                       ldy #3
   420  fe6f 20e3ff                     jsr hbc56CustomDelay
   421  fe72 c636                       dec DELAY_L
   422  fe74 d0f7                       bne -
   423  fe76 a900                       lda #0
   424  fe78 8536                       sta DELAY_L
   425  fe7a c637                       dec DELAY_H
   426  fe7c d0ef                       bne -
   427  fe7e 60                         rts
   428                          
   429                          
   430                          ;!warn "Kernel size: ", *-$f000
