PAGE 01 DAI FIRMWARE DD1A-DEB7 V1.1 002 ORG :DD1A 003 * 004 * 005 * 006 ******************* 007 * INPUT TEXT LINE * 008 ******************* 009 * 010 * Part of 'restart interpreter' (C853). 011 * Scans keyboard and reads in a line on the current 012 * screen line, up until car.ret. First prints 013 * car.ret and a prompt ('*'). 014 * The routine can be aborted on car.ret or Break 015 * only. 016 * 017 * Entry: A: Contains prompt. 018 * Exit: CY=1: Break pressed. 019 * CY=0: HL: Address 1st character on line. 020 * C=1: Offset 1st significant character 021 * ABDEHL preserved. 022 * 023 DD1A F5 INPL0 PUSH PSW 024 DD1B CD55DD CALL :DD55 Cursor to column 0 025 DD1E F1 POP PSW Get prompt 026 DD1F 37 INPLN STC CY=1 027 DD20 F5 PUSH PSW 028 DD21 E5 PUSH H Save cursor coord 1st char 029 DD22 CD6ADD IPL10 CALL :DD6A Print prompt 030 DD25 21B902 LXI H,:02B9 031 DD28 3600 MVI M,:00 Enable complete keyb.scan 032 DD2A CDBED6 IPL20 CALL :D6BE Get keyb. input 033 * 034 ******************* 035 * INPUT TEXT LINE * 036 ******************* 037 * 038 * Added: Output back to screen if break pressed. 039 * This avoids a not-useable keyboard on return. 040 * 041 DD2D DA36CD JC :CD36 ] Jump if break pressed 042 DD30 CA2ADD JZ :DD2A Wait for input 043 DD33 FE20 CPI :20 Printable character? 044 DD35 D222DD JNC :DD22 Print it and get next one 045 DD38 FE08 CPI :08 Backspace 046 DD3A CA22DD JZ :DD22 Print it; get next char 047 DD3D FE0D CPI :0D Car.ret? 048 DD3F C22ADD JNZ :DD2A Get next char if not 049 050 * Exit on car.ret: 051 052 DD42 35 DCR M Set KBRFL for BREAK only 053 DD43 0E01 MVI C,:01 054 DD45 E1 EXIT1 POP H Get cursor coord 1st char 055 DD46 F1 POP PSW Get prompt 056 DD47 3F CMC CY=0 057 DD48 C9 RET 058 059 * Exit on Break: 060 061 DD49 35 IPL30 DCR M Set KBRFL for BREAK only 062 DD4A 3E21 MVI A,:21 063 DD4C CD60DD CALL :DD60 Print '!' PAGE 02 DAI FIRMWARE DD1A-DEB7 V1.1 064 DD4F CD5EDD CALL :DD5E Print car.ret 065 DD52 E1 POP H 066 DD53 F1 POP PSW Get prompt, CY=1 067 DD54 C9 RET 068 * 069 ********************** 070 * CURSOR TO COLUMN 0 * 071 ********************** 072 * 073 * The X-coordinate of the cursor is checked. 074 * If not 0, a car.ret is printed. 075 * 076 * Entry: None. 077 * Exit: AF corrupted. BCDEHL preserved. 078 * 079 DD55 D5 COL0 PUSH D 080 DD56 E5 PUSH H 081 DD57 EF RST 5 Get cursor pos (HL) and size 082 DD58 0C DATA :0C char.screen (DE) 083 DD59 7D MOV A,L X-coord cursor in A 084 DD5A E1 POP H 085 DD5B D1 POP D 086 DD5C B7 ORA A 087 DD5D C8 RZ Abort if cursor in Col.0 088 DD5E 3E0D CRLF MVI A,:0D Else: print CR 089 * 090 * GENERAL OUTPUT ROUTINE: 091 * 092 * Outputs a character in a direction depending 093 * on OTSW (#0131). 094 * 095 * Entry: A: Character to be transmitted. 096 * Exit: AF corrupted. 097 * 098 *SCCHR 099 DD60 F5 OUTC PUSH PSW Preserve char 100 DD61 3A3101 LDA :0131 101 DD64 FE02 CPI :02 Check output direction 102 DD66 D270DD JNC :DD70 If to edit buf/DOUTC 103 104 * To screen/RS232 - OTSW=0/1: 105 106 DD69 F1 POP PSW Get char 107 DD6A EF COUTC RST 5 Character to screen 108 DD6B 03 DATA :03 109 DD6C D442D6 CNC :D642 Output to RS232 if reqd 110 DD6F C9 RET 111 112 * To DOUTC - OTSW=3: 113 114 DD70 00 OTC10 NOP 115 DD71 C24CD7 JNZ :D74C Character to DOUTC 116 117 * To editbuffer - OTSW=2: 118 119 DD74 F1 POP PSW Get char 120 DD75 F5 OTBIN PUSH PSW 121 DD76 E5 PUSH H 122 DD77 D5 PUSH D 123 DD78 2AA400 LHLD :00A4 Get edit input pointer 124 DD7B 77 MOV M,A Byte in edit buffer 125 DD7C 23 INX H PAGE 03 DAI FIRMWARE DD1A-DEB7 V1.1 126 DD7D 22A400 SHLD :00A4 Update edit input pointer 127 DD80 EB XCHG in DE 128 DD81 2AA600 LHLD :00A6 Get end edit buffer 129 DD84 CD14DE CALL :DE14 Calculate free buffer space 130 DD87 DA8EDD JC :DD8E If edit buffer full 131 DD8A D1 POP D 132 DD8B E1 POP H 133 DD8C F1 OTC99 POP PSW 134 DD8D C9 RET 135 136 * If edit buffer full: 137 138 DD8E CDCADE OTC20 CALL :DECA Heap back to right size 139 DD91 C310DA JMP :DA10 Run error 'OUT OF MEMORY' 140 * 141 ******************* 142 * OUTPUT TO RS232 * 143 ******************* 144 * 145 * Transmits a character to the RS232 interface via 146 * the TICC if the interface is ready for it. 147 * In case of a car.ret, also a line feed is send. 148 * 149 * Entry: A: Character to be transmitted. 150 * Exit: ABCDEHL preserved, F corrupted. 151 * 152 DD94 F5 OUTSE PUSH PSW Preserve char 153 DD95 3A00FD OTS10 LDA :FD00 154 DD98 E608 ANI :08 Check peripheral ready 155 DD9A CA95DD JZ :DD95 Wait untill ready 156 DD9D 3AF3FF OTS20 LDA :FFF3 157 DDA0 E610 ANI :10 Check TICC buffer empty 158 DDA2 CA9DDD JZ :DD9D Wait untill empty 159 DDA5 F1 POP PSW Get char 160 DDA6 32F6FF STA :FFF6 Load serial output buffer 161 DDA9 FE0D CPI :0D Carriage return? 162 DDAB C0 RNZ Ready if not 163 164 * If car.ret: 165 166 DDAC F5 PUSH PSW 167 DDAD 3E0A MVI A,:0A 168 DDAF CD94DD CALL :DD94 Send line feed too 169 DDB2 F1 POP PSW 170 DDB3 C9 RET 171 * 172 ******************** 173 * INPUT FROM RS232 * 174 ******************** 175 * 176 * Gets inputs from RS232 via TICC. Only 7-bit 177 * Ascii-code is accepted. 178 * 179 * Entry: No conditions. 180 * Exit: A: Character received (0 if nothing). 181 * BCDEHL preserved. 182 * 183 *CINC 184 DDB4 3AF3FF INSER LDA :FFF3 185 DDB7 E608 ANI :08 Check if something received 186 DDB9 C8 RZ Abort if no reception 187 DDBA 3AF0FF LDA :FFF0 Received char in A PAGE 04 DAI FIRMWARE DD1A-DEB7 V1.1 188 DDBD E67F ANI :7F Mask bit 7 189 DDBF C9 RET 190 * 191 ********************************** 192 * RS232 FRAME ERROR - (not used) * 193 ********************************** 194 * 195 * Break test for serial input line. 196 * 197 DDC0 3AF3FF BRSER LDA :FFF3 198 DDC3 1F RAR 199 DDC4 D0 RNC Abort if no break 200 DDC5 3AF3FF BRS10 LDA :FFF3 If break: check again 201 DDC8 1F RAR 202 DDC9 DAC5DD JC :DDC5 Wait until end of break 203 DDCC 3AF0FF LDA :FFF0 Load received character 204 DDCF 3F CMC Set CY=1 205 DDD0 C9 RET 206 * 207 * 208 * =========================== 209 *** ENCODING SERVICE ROUTINES *** 210 * =========================== 211 * 212 * 213 * The following routines are used both in 'main' 214 * and 'decode' modules. 215 * 216 ************************************************ 217 * GET CHARACTER FROM LINE, NEGLECT TAB + SPACE * 218 ************************************************ 219 * 220 * Entry: C: Position on current line. 221 * Exit: Character in A; tab and space neglected. 222 * C: Points to next character. 223 * BDEHL preserved. 224 * 225 DDD1 0C IGNBR INR C Pnts to next char 226 DDD2 CDE0DD IGNB CALL :DDE0 Get char from line 227 DDD5 FE20 CPI :20 Space? 228 DDD7 CAD1DD JZ :DDD1 Then get next char 229 DDDA FE09 CPI :09 Tab? 230 DDDC CAD1DD JZ :DDD1 Then get next char 231 DDDF C9 RET 232 * 233 *************************** 234 * GET CHARACTER TO ENCODE * 235 *************************** 236 * 237 * Returns a character from some position on the 238 * current line. The source is determined by EFSW. 239 * 240 * Entry: C: Position on current line (max. 219). 241 * Exit: EFSW=0 - Keyboard: Char on line pos in A. 242 * EFSW>=2 - Edit buf: Char on EFEPT + line 243 * pos in A. 244 * EFSW=1 - String: Idem. If COUNT=line pos 245 * then char is car.ret. 246 * F corrupted, BCDEHL preserved. 247 * 248 DDE0 3A3501 EFETCH LDA :0135 249 DDE3 FE01 CPI :01 Check input direction PAGE 05 DAI FIRMWARE DD1A-DEB7 V1.1 250 DDE5 DAFFDD JC :DDFF If from keyb/RS232 251 DDE8 C2F4DD JNZ :DDF4 If from edit buffer 252 253 * If from string: 254 255 DDEB 3A3401 LDA :0134 If string: Get COUNT 256 DDEE B9 CMP C COUNT=pos.on curr.line? 257 DDEF 3E0D MVI A,:0D Then char is car.ret 258 DDF1 CAFEDD JZ :DDFE And abort 259 260 * Entry if from edit buffer: 261 262 DDF4 E5 EFC10 PUSH H 263 DDF5 2A3201 LHLD :0132 Get EFEPT 264 DDF8 79 MOV A,C 265 DDF9 CD30DE CALL :DE30 Add curr.line pos to EFEPT 266 DDFC 7E MOV A,M Get character 267 DDFD E1 POP H 268 DDFE C9 EFC20 RET 269 270 * If from screen: 271 272 DDFF EF EFC30 RST 5 Get character from line 273 DE00 15 DATA :15 274 DE01 C9 RET 275 * 276 * 277 * ================================== 278 *** SINGLE AND DOUBLE BYTE UTILITIES *** 279 * ================================== 280 * 281 * 282 ********************************* 283 * CHECK IF UPPER CASE CHARACTER * 284 ********************************* 285 * 286 * Entry: A: Character to be checked. 287 * Exit: CY=0: Not upper case. 288 * CY=1: Upper case. 289 * ABCDEHL preserved, F corrupted. 290 * 291 DE02 FE41 ALPHA CPI :41 Lowest upper case char 292 DE04 3F CMC 293 DE05 D0 RNC 294 DE06 FE5B CPI :5B First lower case char 295 DE08 C9 RET 296 * 297 ********************************************** 298 * CHECK IF CHARACTER IS NUMBER OR UPPER CASE * 299 ********************************************** 300 * 301 * Entry: A: Character to be checked. 302 * Exit: CY=0: Not number, not upper case. 303 * CY=1: Number or upper case. 304 * ABCDEHL preserved. F corrupted. 305 * 306 DE09 CD02DE ALNUM CALL :DE02 Check if upper case 307 DE0C D8 RC 308 DE0D FE30 NUMER CPI :30 Lowest number 309 DE0F 3F CMC 310 DE10 D0 RNC 311 DE11 FE3A CPI :3A No number anymore PAGE 06 DAI FIRMWARE DD1A-DEB7 V1.1 312 DE13 C9 RET 313 * 314 ********************* 315 * COMPARE HL AND DE * 316 ********************* 317 * 318 * Compares HL with DE (HL-DE). 319 * 320 * Exit: DE=HL: Z=1, CY=0. 321 * DEHL: Z=0, CY=1. 323 * BCDEHL preserved, AF corrupted. 324 * 325 DE14 7C COMP MOV A,H 326 DE15 BA CMP D 327 DE16 C0 RNZ 328 DE17 7D MOV A,L 329 DE18 BB CMP E 330 DE19 C9 RET 331 * 332 ***************************** 333 * CALCULATE LENGTH OF BLOCK * 334 ***************************** 335 * 336 * Sets HL=HL-DE. 337 * 338 * Entry: Startaddress in DE, 1st address after 339 * block in HL. 340 * Exit: Length in HL, startaddress in DE. 341 * If DE>HL, length in 2-complement. 342 * ABCDE preserved, F as in COMP. 343 * 344 DE1A C5 SUBDE PUSH B 345 DE1B F5 PUSH PSW 346 DE1C 7D MOV A,L 347 DE1D 93 SUB E Calc. difference lowest byte 348 DE1E 6F MOV L,A 349 DE1F 7C MOV A,H 350 DE20 9A SBB D Calc. diff. highest byte 351 DE21 67 MOV H,A 352 DE22 C1 POP B 353 DE23 78 MOV A,B 354 DE24 C1 POP B 355 DE25 C9 RET 356 * 357 ****************************** 358 * DOUBLE BYTE TWO COMPLEMENT * 359 ****************************** 360 * 361 * Sets HL=-HL. 362 * 363 * Entry: Double byte to be converted in HL. 364 * Exit: Two complement in HL. ABCDEF preserved. 365 * 366 DE26 F5 CMPHL PUSH PSW 367 DE27 7C MOV A,H 368 DE28 2F CMA Complement H 369 DE29 67 MOV H,A 370 DE2A 7D MOV A,L 371 DE2B 2F CMA Complement L 372 DE2C 6F MOV L,A 373 DE2D 23 INX H Add 1 PAGE 07 DAI FIRMWARE DD1A-DEB7 V1.1 374 DE2E F1 POP PSW 375 DE2F C9 RET 376 * 377 ************************** 378 * ADD OFF-SET TO ADDRESS * 379 ************************** 380 * 381 * Adds a given offset to a base address (HL=HL+A). 382 * 383 * Entry: Base in HL, offset in A. 384 * Exit: HL=HL+A. ABCDE preserved, F corrupted. 385 * 386 DE30 F5 DADA PUSH PSW 387 DE31 85 ADD L 388 DE32 6F MOV L,A L=L+A 389 DE33 7C MOV A,H 390 DE34 CE00 ACI :00 Add carry if overflow 391 DE36 67 MOV H,A 392 DE37 F1 POP PSW 393 DE38 C9 RET 394 * 395 ********************************** 396 * CALCULATE ADDRESS AFTER STRING * 397 ********************************** 398 * 399 * Sets HL=HL+M+1. 400 * 401 * Entry: HL points to 1st byte of string (length 402 * byte). 403 * Exit: HL points to first byte after string. 404 * AFBCDE preserved. 405 * 406 DE39 F5 DADM PUSH PSW 407 DE3A 7E MOV A,M Get length of string 408 DE3B 23 INX H HL: addr. 1st char. byte 409 DE3C CD30DE CALL :DE30 Calc addr after string 410 DE3F F1 POP PSW 411 DE40 C9 RET 412 * 413 ***************** 414 * DELAY ROUTINE * 415 ***************** 416 * 417 * Runs a fixed delay loop of 665 msec. If 418 * interrupts are enabled, the delay will be 419 * approx. 750 msec. 420 * HL is loaded with FFFF, and then decremented. 421 * 422 * Exit: ABCDEHL preserved; F corrupted. 423 * 424 DE41 E5 DELAY PUSH H 425 DE42 D5 PUSH D 426 DE43 21FFFF LXI H,:FFFF Init. delay value 427 DE46 54 MOV D,H 428 DE47 5D MOV E,L 429 DE48 19 DLY10 DAD D 430 DE49 DA48DE JC :DE48 Repeat if not ready 431 DE4C D1 POP D 432 DE4D E1 POP H 433 DE4E C9 RET 434 * 435 *********************** PAGE 08 DAI FIRMWARE DD1A-DEB7 V1.1 436 * DATA BLOCK TRANSFER * 437 *********************** 438 * 439 * Moves a block of data starting at (DE) and 440 * ending at (HL)-1 to (BC). 441 * 442 * Entry: DE: Startaddr. source bank. 443 * BC: Startaddr. destination bank. 444 * HL: Points after end source bank. 445 * Exit: AF preserved, BCDEHL corrupted. 446 * 447 DE4F F5 MOVE PUSH PSW 448 DE50 E5 PUSH H 449 DE51 CD1ADE CALL :DE1A Calc. length source bank 450 DE54 79 MOV A,C 451 DE55 93 SUB E 452 DE56 78 MOV A,B 453 DE57 9A SBB D 454 DE58 DA6CDE JC :DE6C If destination addr. is 455 lower than source addr. 456 457 * Destination address > source address: 458 459 DE5B 54 MOV D,H 460 DE5C 5D MOV E,L Save length in DE 461 DE5D 09 DAD B Highest dest.addr. in HL 462 DE5E C1 POP B 463 DE5F 7A MOV10 MOV A,D Check if ready 464 DE60 B3 ORA E 465 DE61 CA7ADE JZ :DE7A Then abort 466 DE64 1B DCX D 467 DE65 2B DCX H 468 DE66 0B DCX B 469 DE67 0A LDAX B Get byte to be transferred 470 DE68 77 MOV M,A Transfer it 471 DE69 C35FDE JMP :DE5F Next one 472 473 * Destination address < source address: 474 475 DE6C 7C MOV20 MOV A,H 476 DE6D B5 ORA L 477 DE6E CA79DE JZ :DE79 Abort if ready 478 DE71 2B DCX H 479 DE72 1A LDAX D Get byte to be transferred 480 DE73 02 STAX B Transfer it 481 DE74 13 INX D 482 DE75 03 INX B 483 DE76 C36CDE JMP :DE6C Next byte 484 485 * If ready: 486 487 DE79 E1 MOV30 POP H 488 DE7A F1 MOV40 POP PSW 489 DE7B C9 RET 490 * 491 ********************************* 492 * FILL BANK WITH IDENTICAL DATA * 493 ********************************* 494 * 495 * Fills an area of memory with a constant. 496 * 497 * Entry: DE: Startaddr. of bank. PAGE 09 DAI FIRMWARE DD1A-DEB7 V1.1 498 * HL: Points after bank. 499 * A: Data to be loaded into bank. 500 * Exit: DE: Points after bank. 501 * BCHL preserved, AF corrupted. 502 * 503 DE7C C5 FILL PUSH B 504 DE7D 47 MOV B,A Save data in B 505 DE7E CD14DE FIL10 CALL :DE14 Check if bank full 506 DE81 CA8DDE JZ :DE8D Abort if ready 507 DE84 DA8DDE JC :DE8D Abort if DE>HL 508 DE87 78 MOV A,B Get data 509 DE88 12 STAX D and store it 510 DE89 13 INX D 511 DE8A C37EDE JMP :DE7E Next addr. 512 DE8D C1 FIL20 POP B 513 DE8E C9 RET 514 * 515 ******************** 516 * MULTIPLY HL BY A * 517 ******************** 518 * 519 * Multiplies a 16-bit value by a 8-bit value. 520 * 521 * Entry: HL: 16-bit value. 522 * A: 8-bit value. 523 * Exit: CY=0: Result in HL. 524 * CY=1: Overflow. 525 * ABCDE preserved. 526 * 527 DE8F 37 HLMUL STC 528 DE90 F5 PUSH PSW 529 DE91 D5 PUSH D 530 DE92 EB XCHG 531 DE93 210000 LXI H,:0000 Init. result 532 DE96 B7 HLM10 ORA A 533 DE97 1F RAR Next bit of multiplier 534 DE98 D29FDE JNC :DE9F Jump if bit is 0 535 DE9B 19 DAD D Add 1* HL if bit is 1 536 * 537 ******************* 538 * MULTIPLY HL * A * 539 ******************* 540 * 541 * Routine only moved. 542 * 543 DE9C DAA9DE JC :DEA9 ! 544 DE9F B7 ORA A 545 DEA0 CAACDE JZ :DEAC ! 546 DEA3 EB XCHG 547 DEA4 29 DAD H 548 DEA5 EB XCHG 549 DEA6 D296DE JNC :DE96 550 DEA9 D1 POP D 551 DEAA F1 POP PSW 552 DEAB C9 RET 553 DEAC D1 POP D 554 DEAD F1 POP PSW 555 DEAE 3F CMC 556 DEAF C9 RET 557 * 558 *********** 559 * RUN NEW * PAGE 10 DAI FIRMWARE DD1A-DEB7 V1.1 560 *********** 561 * 562 * - An additional entry is made for run NEW with 563 * returning the heapsize to its default value. 564 * In BASIC V1.0, this entry was available on 565 * #CEC6. 566 * - All jumps/calls to RNEW with other heapsizes 567 * are updated. 568 * 569 DEB0 210001 LXI H,:0100 ] 570 DEB3 229D02 SHLD :029D ] Set heap to default size 571 DEB6 00 NOP 572 DEB7 00 NOP Into RNEW 573 * 574 * 575 * 580 DEB8 END *************************** * S Y M B O L T A B L E * *************************** ALNUM DE09 ALPHA DE02 BRS10 DDC5 BRSER DDC0 CINC DDB4 CMPHL DE26 COL0 DD55 COMP DE14 COUTC DD6A CRLF DD5E DADA DE30 DADM DE39 DELAY DE41 DLY10 DE48 EFC10 DDF4 EFC20 DDFE EFC30 DDFF EFETCH DDE0 EXIT1 DD45 FIL10 DE7E FIL20 DE8D FILL DE7C HLM10 DE96 HLMUL DE8F IGNB DDD2 IGNBR DDD1 INPL0 DD1A INPLN DD1F INSER DDB4 IPL10 DD22 IPL20 DD2A IPL30 DD49 MOV10 DE5F MOV20 DE6C MOV30 DE79 MOV40 DE7A MOVE DE4F NUMER DE0D OTBIN DD75 OTC10 DD70 OTC20 DD8E OTC99 DD8C OTS10 DD95 OTS20 DD9D OUTC DD60 OUTSE DD94 SCCHR DD60 SUBDE DE1A