; MS-BASIC START UP ROUTINE ; TARGET: AKI-80 M2 with Watch ; ASSEMBLER: ARCPIT XZ80.EXE ; HZ EQU 10 ; System Clock 12 or 10 ; TSTACK EQU 80EDH ; CTC0 EQU 10H PCTCC2 EQU 13H ; Changed from 12H to 13H PSIOAD EQU 18H PSIOAC EQU 19H PSIOBD EQU 1AH PSIOBC EQU 1BH PIOA EQU 1CH PIOB EQU 1EH ; CR EQU 0DH LF EQU 0AH ; ; SYSTEM PARAMETERS ORG 08100H RBFCNT DS 01H RBFRDP DS 01H RBFWTP DS 01H RECBUF DS 40H ; ; ; RESET VECTOR ORG 0000H RST00: DI JP SINIT ; ; RESTART VECTOR ORG 0008H RST08: JP TXA ORG 0010H RST10: JP RXA ORG 0018H RST18: JP KBHIT ; ; SIOA -> BUFFER BY INTERRUPT INTRCV: di PUSH AF PUSH BC PUSH DE PUSH HL ; DI IN A,(PSIOAC) ;CHECK RECEIVE BIT 0,A ;IF NOT JR Z,RWTEXT ;EXIT IN A,(PSIOAD) ;GET DATA LD D,A ;SAVE TO D LD A,(RBFCNT) ;GET COUNT CP 40H ;IF BUFFER FULL JR Z,RWTEXT ;EXIT(GIVE UP!) STRWT3: INC A ;COUNT UP LD (RBFCNT),A ;COUNT UPDATE LD A,(RBFWTP) ;GET OFFSET LD C,A ;C, OFFSET LOW LD B,00H ;B, OFFSET HIGH LD HL,RECBUF ;HL, BUFFER TOP ADD HL,BC ;HL, WRITE POINT IN BUFFER LD (HL),D ;WRITE DATA INC A ;OFFSET INCREMENT AND 3FH ;WRAP LD (RBFWTP),A ;OFFSET UPDATE RWTEXT: POP HL POP DE POP BC POP AF EI RETI ; ; ; BUFER -> A RXA: PUSH BC PUSH DE PUSH HL LOPRBR: LD A,(RBFCNT) ;GET COUNT CP 00H ;CHECK RECEIVE JR Z,LOPRBR ;WAIT FOR RECEIVE DI ;DISABLE INTERRUPT DEC A ;COUNT DOWN LD (RBFCNT),A ;COUNT UPDATE LD A,(RBFRDP) ;GET OFFSET LD C,A ;C, OFFSET LOW LD B,00H ;B, OFFSET HIGH LD HL,RECBUF ;HL, BUFFER TOP ADD HL,BC ;HL, READ POINT IN BUFFER LD D,(HL) ;READ DATA INC A ;OFFSET INCREMENT AND 3FH ;WRAP LD (RBFRDP),A ;OFFSET UPDATE LD A,D ;GET DATA EI ;ENABLE INTERRUPT POP HL POP DE POP BC RET ; ; A -> SIO TXA: PUSH AF ;SAVE DATA TXLOOP: IN A,(PSIOAC) ;CHECK STATUS BIT 2,A ;IF BUFFER NOT EMPTY JR Z,TXLOOP ;WAIT FOR EMPTY POP AF ;RESTORE DATA OUT (PSIOAD),A ;TRANSFER RET ; ; CHECK RECEIVE STATUS KBHIT: LD A,(RBFCNT) CP 00H RET ; ; INTERRUPT VECTORS ORG (($-1) AND 0FFF0H) + 10H VECTOR: DW INTX ; M2 Interrupt Table DW 0H DW 0H DW 0H INTVCT: DW INTRCV ; ; SIOA COMMAND CHAIN SIOACD: DB 00011000B ;RESET DB 01H,00010000B ;RX INTERRUPT ENABLE DB 04H,01000100B ;FORMAT DB 05H,11101010B ;TX ENABLE DB 03H,11000001B ;RX ENABLE SIOACL EQU $-SIOACD ; ; SIOB COMMAND CHAIN SIOBCD: DB 00011000B ;RESET DB 01H,00000000B ;DISABLE STATUS/AFFECTS VECTOR DB 02H,INTVCT AND 00FFH ;SET INTERRUPT VECTOR SIOBCL EQU $-SIOBCD ; ; SYSTEM INITIALIZE SINIT: LD SP,TSTACK XOR A LD (RBFCNT),A LD (RBFRDP),A LD (RBFWTP),A ; ; CTC INITIALIZE LD A,00000111B OUT (PCTCC2),A if (HZ=12) LD A,5 ;12MHz else LD A,4 ;9.8304MHz endif OUT (PCTCC2),A ; ; SIO INITIALIZE LD B,SIOACL ;LENGTH LD C,PSIOAC ;I/O ADDRESS LD HL,SIOACD ;COMMAND ADDRESS OTIR LD B,SIOBCL ;LENGTH LD C,PSIOBC ;I/O ADDRESS LD HL,SIOBCD ;COMMAND ADDRESS OTIR ; ; SETUP INTERRUPT LD HL,INTVCT LD A,H LD I,A IM 2 EI ; ; ; ; START BASIC CALL CLOCK JP COLD ; ;================================================================================== ; The updates to the original BASIC within this file are copyright Grant Searle ; ; You have permission to use this for NON COMMERCIAL USE ONLY ; If you wish to use it elsewhere, please include an acknowledgement to myself. ; ; http://searle.hostei.com/grant/index.html ; ; eMail: home.micros01@btinternet.com ; ; If the above don't work, please perform an Internet search to see if I have ; updated the web page hosting service. ; ;================================================================================== ; ; NASCOM ROM BASIC Ver 4.7, (C) 1978 Microsoft ; Scanned from source published in 80-BUS NEWS from Vol 2, Issue 3 ; (May-June 1983) to Vol 3, Issue 3 (May-June 1984) ; Adapted for the freeware Zilog Macro Assembler 2.10 to produce ; the original ROM code (checksum A934H). PA ; ; GENERAL EQUATES ; CTRLC EQU 03H ; Control "C" CTRLG EQU 07H ; Control "G" BKSP EQU 08H ; Back space LF EQU 0AH ; Line feed CS EQU 0CH ; Clear screen CR EQU 0DH ; Carriage return CTRLO EQU 0FH ; Control "O" CTRLQ EQU 11H ; Control "Q" CTRLR EQU 12H ; Control "R" CTRLS EQU 13H ; Control "S" CTRLU EQU 15H ; Control "U" ESC EQU 1BH ; Escape DEL EQU 7FH ; Delete ; ; BASIC WORK SPACE LOCATIONS ; RAMTOP EQU 8000H ; ID No MS EQU RAMTOP+2 SEC EQU MS+2 MIN EQU SEC+1 ; 1 Byte Size HOR EQU MIN+1 DAY EQU HOR+1 PADIR EQU DAY+1 PADT EQU PADIR+1 PBDIR EQU PADT+1 PBDT EQU PBDIR+1 AFREG EQU PBDT+2 BCREG EQU AFREG+2 DEREG EQU BCREG+2 HLREG EQU DEREG+2 ; WRKSPC EQU 8145H ; BASIC Work space USR EQU WRKSPC+3H ; "USR (x)" jump OUTSUB EQU WRKSPC+6H ; "OUT p,n" OTPORT EQU WRKSPC+7H ; Port (p) DIVSUP EQU WRKSPC+9H ; Division support routine DIV1 EQU WRKSPC+0AH ; <- Values DIV2 EQU WRKSPC+0EH ; <- to DIV3 EQU WRKSPC+12H ; <- be DIV4 EQU WRKSPC+15H ; <- inserted SEED EQU WRKSPC+17H ; Random number seed LSTRND EQU WRKSPC+3AH ; Last random number INPSUB EQU WRKSPC+3EH ; #INP (x)" Routine INPORT EQU WRKSPC+3FH ; PORT (x) NULLS EQU WRKSPC+41H ; Number of nulls LWIDTH EQU WRKSPC+42H ; Terminal width COMMAN EQU WRKSPC+43H ; Width for commas NULFLG EQU WRKSPC+44H ; Null after input byte flag CTLOFG EQU WRKSPC+45H ; Control "O" flag LINESC EQU WRKSPC+46H ; Lines counter LINESN EQU WRKSPC+48H ; Lines number CHKSUM EQU WRKSPC+4AH ; Array load/save check sum NMIFLG EQU WRKSPC+4CH ; Flag for NMI break routine BRKFLG EQU WRKSPC+4DH ; Break flag RINPUT EQU WRKSPC+4EH ; Input reflection POINT EQU WRKSPC+51H ; "POINT" reflection (unused) PSET EQU WRKSPC+54H ; "SET" reflection RESET EQU WRKSPC+57H ; "RESET" reflection STRSPC EQU WRKSPC+5AH ; Bottom of string space LINEAT EQU WRKSPC+5CH ; Current line number BASTXT EQU WRKSPC+5EH ; Pointer to start of program BUFFER EQU WRKSPC+61H ; Input buffer STACK EQU WRKSPC+66H ; Initial stack CURPOS EQU WRKSPC+0ABH ; Character position on line LCRFLG EQU WRKSPC+0ACH ; Locate/Create flag TYPE EQU WRKSPC+0ADH ; Data type flag DATFLG EQU WRKSPC+0AEH ; Literal statement flag LSTRAM EQU WRKSPC+0AFH ; Last available RAM TMSTPT EQU WRKSPC+0B1H ; Temporary string pointer TMSTPL EQU WRKSPC+0B3H ; Temporary string pool TMPSTR EQU WRKSPC+0BFH ; Temporary string STRBOT EQU WRKSPC+0C3H ; Bottom of string space CUROPR EQU WRKSPC+0C5H ; Current operator in EVAL LOOPST EQU WRKSPC+0C7H ; First statement of loop DATLIN EQU WRKSPC+0C9H ; Line of current DATA item FORFLG EQU WRKSPC+0CBH ; "FOR" loop flag LSTBIN EQU WRKSPC+0CCH ; Last byte entered READFG EQU WRKSPC+0CDH ; Read/Input flag BRKLIN EQU WRKSPC+0CEH ; Line of break NXTOPR EQU WRKSPC+0D0H ; Next operator in EVAL ERRLIN EQU WRKSPC+0D2H ; Line of error CONTAD EQU WRKSPC+0D4H ; Where to CONTinue PROGND EQU WRKSPC+0D6H ; End of program VAREND EQU WRKSPC+0D8H ; End of variables ARREND EQU WRKSPC+0DAH ; End of arrays NXTDAT EQU WRKSPC+0DCH ; Next data item FNRGNM EQU WRKSPC+0DEH ; Name of FN argument FNARG EQU WRKSPC+0E0H ; FN argument value FPREG EQU WRKSPC+0E4H ; Floating point register FPEXP EQU FPREG+3 ; Floating point exponent SGNRES EQU WRKSPC+0E8H ; Sign of result PBUFF EQU WRKSPC+0E9H ; Number print buffer MULVAL EQU WRKSPC+0F6H ; Multiplier PROGST EQU WRKSPC+0F9H ; Start of program text area STLOOK EQU WRKSPC+15DH ; Start of memory test ; ; BASIC ERROR CODE VALUES ; NF EQU 00H ; NEXT without FOR SN EQU 02H ; Syntax error RG EQU 04H ; RETURN without GOSUB OD EQU 06H ; Out of DATA FC EQU 08H ; Function call error OV EQU 0AH ; Overflow OM EQU 0CH ; Out of memory UL EQU 0EH ; Undefined line number BS EQU 10H ; Bad subscript RD EQU 12H ; Re-DIMensioned array DZ EQU 14H ; Division by zero (/0) ID EQU 16H ; Illegal direct TM EQU 18H ; Type miss-match OS EQU 1AH ; Out of string space LS EQU 1CH ; String too long ST EQU 1EH ; String formula too complex CN EQU 20H ; Can't CONTinue UF EQU 22H ; UnDEFined FN function MO EQU 24H ; Missing operand HX EQU 26H ; HEX error BN EQU 28H ; BIN error ; COLD: JP STARTB ; Jump for cold start WARM: JP WARMST ; Jump for warm start STARTB: JP CSTART ; Jump to initialise ; DW DEINT ; Get integer -32768 to 32767 DW ABPASS ; Return integer in AB ; CSTART: LD HL,WRKSPC ; Start of workspace RAM LD SP,HL ; Set up a temporary stack LD A,0002H ;ID No. LD (RAMTOP),A XOR A LD (DAY),A LD (HOR),A LD (MIN),A LD (SEC),A LD DE,0 LD HL,BSRAM LD BC,BSRAM1-BSRAM LDIR LD A,5 OUT (01BH),a LD A,06AH OUT (01BH),A JP INITST ; Go to initialise ; INIT: LD DE,INITAB ; Initialise workspace LD B,INITBE-INITAB+3; Bytes to copy LD HL,WRKSPC ; Into workspace RAM COPY: LD A,(DE) ; Get source LD (HL),A ; To destination INC HL ; Next destination INC DE ; Next source DEC B ; Count bytes JP NZ,COPY ; More to move LD SP,HL ; Temporary stack CALL CLREG ; Clear registers and stack CALL PRCRLF ; Output CRLF LD (BUFFER+72+1),A ; Mark end of buffer LD (PROGST),A ; Initialise program area MSIZE: LD HL,STLOOK ; Point to start of RAM MLOOP: INC HL ; Next byte LD A,H ; Above address FFFF ? OR L JP Z,SETTOP ; Yes - 64K RAM LD A,(HL) ; Get contents LD B,A ; Save it CPL ; Flip all bits LD (HL),A ; Put it back CP (HL) ; RAM there if same LD (HL),B ; Restore old contents JP Z,MLOOP ; If RAM - test next byte ; SETTOP: DEC HL ; Back one byte LD DE,STLOOK-1 ; See if enough RAM CALL CPDEHL ; Compare DE with HL JP C,NEMEM ; If not enough RAM LD DE,0-50 ; 50 Bytes string space LD (LSTRAM),HL ; Save last available RAM ADD HL,DE ; Allocate string space LD (STRSPC),HL ; Save string space CALL CLRPTR ; Clear program area LD HL,(STRSPC) ; Get end of memory LD DE,0-17 ; Offset for free bytes ADD HL,DE ; Adjust HL LD DE,PROGST ; Start of program text LD A,L ; Get LSB SUB E ; Adjust it LD L,A ; Re-save LD A,H ; Get MSB SBC A,D ; Adjust it LD H,A ; Re-save PUSH HL ; Save bytes free LD HL,SIGNON ; Sign-on message CALL PRS ; Output string POP HL ; Get bytes free back CALL PRNTHL ; Output amount of free memory LD HL,BFREE ; " Bytes free" message CALL PRS ; Output string ; WARMST: LD SP,STACK ; Temporary stack BRKRET: CALL CLREG ; Clear registers and stack JP PRNTOK ; Go to get command line ; NEMEM: LD HL,MEMMSG ; Memory size not enough CALL PRS ; Print it XXXXX: JP XXXXX ; Stop ; BFREE: DB " Bytes free",CR,LF,0,0 ; SIGNON: DB "Z80 BASIC Ver 4.7b",CR,LF DB "Copyright ",40,"C",41 DB " 1978 by Microsoft on ROM",CR,LF,0,0 ; MEMMSG: DB "Memory size not enough",CR,LF DB "The system is stopped.",CR,LF,0,0 ; ; FUNCTION ADDRESS TABLE ; FNCTAB: DW SGN DW INT DW ABS DW USR DW FRE DW INP DW POS DW SQR DW RND DW LOG DW EXP DW COS DW SIN DW TAN DW ATN DW PEEK DW DEEK DW POINT DW LEN DW STR DW VAL DW ASC DW CHR DW HEX DW BIN DW LEFT DW RIGHT DW MID ; ; RESERVED WORD LIST ; WORDS: DB 0C5H,"ND" DB 0C6H,"OR" DB 0CEH,"EXT" DB 0C4H,"ATA" DB 0C9H,"NPUT" DB 0C4H,"IM" DB 0D2H,"EAD" DB 0CCH,"ET" DB 0C7H,"OTO" DB 0D2H,"UN" DB 0C9H,"F" DB 0D2H,"ESTORE" DB 0C7H,"OSUB" DB 0D2H,"ETURN" DB 0D2H,"EM" DB 0D3H,"TOP" DB 0CFH,"UT" DB 0CFH,"N" DB 0CEH,"ULL" DB 0D7H,"AIT" DB 0C4H,"EF" DB 0D0H,"OKE" DB 0C4H,"OKE" DB 0D3H,"CREEN" DB 0CCH,"INES" DB 0C3H,"LS" DB 0D7H,"IDTH" DB 0CDH,"ONITOR" DB 0D3H,"ET" DB 0D2H,"ESET" DB 0D0H,"RINT" DB 0C3H,"ONT" DB 0CCH,"IST" DB 0C3H,"LEAR" DB 0D0H,"P" DB 0CCH,"OAD" DB 0CEH,"EW" ; DB 0D4H,"AB(" DB 0D4H,"O" DB 0C6H,"N" DB 0D3H,"PC(" DB 0D4H,"HEN" DB 0CEH,"OT" DB 0D3H,"TEP" ; DB 0ABH DB 0ADH DB 0AAH DB 0AFH DB 0DEH DB 0C1H,"ND" DB 0CFH,"R" DB 0BEH DB 0BDH DB 0BCH ; DB 0D3H,"GN" DB 0C9H,"NT" DB 0C1H,"BS" DB 0D5H,"SR" DB 0C6H,"RE" DB 0C9H,"NP" DB 0D0H,"OS" DB 0D3H,"QR" DB 0D2H,"ND" DB 0CCH,"OG" DB 0C5H,"XP" DB 0C3H,"OS" DB 0D3H,"IN" DB 0D4H,"AN" DB 0C1H,"TN" DB 0D0H,"EEK" DB 0C4H,"EEK" DB 0D0H,"OINT" DB 0CCH,"EN" DB 0D3H,"TR$" DB 0D6H,"AL" DB 0C1H,"SC" DB 0C3H,"HR$" DB 0C8H,"EX$" DB 0C2H,"IN$" DB 0CCH,"EFT$" DB 0D2H,"IGHT$" DB 0CDH,"ID$" DB 80H ; End of list marker ; ; KEYWORD ADDRESS TABLE ; WORDTB: DW PEND DW FOR DW NEXT DW DATA DW INPUT DW DIM DW READ DW LET DW GOTO DW RUN DW IF DW RESTOR DW GOSUB DW RETURN DW REM DW STOP DW POUT DW ON DW NULL DW WAIT DW DEF DW POKE DW DOKE DW REM DW LINES DW CLS DW WIDTH DW MONITR DW PSET DW RESET DW PRINT DW CONT DW LIST DW CLEAR DW PP DW LOAD DW NEW ; ; RESERVED WORD TOKEN VALUES ; ZEND EQU 080H ; END ZFOR EQU 081H ; FOR ZDATA EQU 083H ; DATA ZGOTO EQU 088H ; GOTO ZGOSUB EQU 08CH ; GOSUB ZREM EQU 08EH ; REM ZPRINT EQU 09EH ; PRINT ZNEW EQU 0A4H ; NEW ; ZTAB EQU 0A5H ; TAB ZTO EQU 0A6H ; TO ZFN EQU 0A7H ; FN ZSPC EQU 0A8H ; SPC ZTHEN EQU 0A9H ; THEN ZNOT EQU 0AAH ; NOT ZSTEP EQU 0ABH ; STEP ; ZPLUS EQU 0ACH ; + ZMINUS EQU 0ADH ; - ZTIMES EQU 0AEH ; * ZDIV EQU 0AFH ; / ZOR EQU 0B2H ; OR ZGTR EQU 0B3H ; > ZEQUAL EQU 0B4H ; M ZLTH EQU 0B5H ; < ZSGN EQU 0B6H ; SGN ZPOINT EQU 0C7H ; POINT ZLEFT EQU 0CDH +2 ; LEFT$ ; ; ARITHMETIC PRECEDENCE TABLE ; PRITAB: DB 79H ; Precedence value DW PADD ; FPREG = + FPREG ; DB 79H ; Precedence value DW PSUB ; FPREG = - FPREG ; DB 7CH ; Precedence value DW MULT ; PPREG = * FPREG ; DB 7CH ; Precedence value DW DIV ; FPREG = / FPREG ; DB 7FH ; Precedence value DW POWER ; FPREG = ^ FPREG ; DB 50H ; Precedence value DW PAND ; FPREG = AND FPREG ; DB 46H ; Precedence value DW POR ; FPREG = OR FPREG ; ; BASIC ERROR CODE LIST ; ERRORS: DB "NF" ; NEXT without FOR DB "SN" ; Syntax error DB "RG" ; RETURN without GOSUB DB "OD" ; Out of DATA DB "FC" ; Illegal function call DB "OV" ; Overflow error DB "OM" ; Out of memory DB "UL" ; Undefined line DB "BS" ; Bad subscript DB "DD" ; Re-DIMensioned array DB "/0" ; Division by zero DB "ID" ; Illegal direct DB "TM" ; Type mis-match DB "OS" ; Out of string space DB "LS" ; String too long DB "ST" ; String formula too complex DB "CN" ; Can't CONTinue DB "UF" ; Undefined FN function DB "MO" ; Missing operand DB "HX" ; HEX error DB "BN" ; BIN error ; ; INITIALISATION TABLE ------------------------------------------------------- ; INITAB: JP WARMST ; Warm start jump JP FCERR ; "USR (X)" jump (Set to Error) OUT (0),A ; "OUT p,n" skeleton RET SUB 0 ; Division support routine LD L,A LD A,H SBC A,0 LD H,A LD A,B SBC A,0 LD B,A LD A,0 RET DB 0,0,0 ; Random number seed table used by RND DB 035H,04AH,0CAH,099H ;-2.65145E+07 DB 039H,01CH,076H,098H ; 1.61291E+07 DB 022H,095H,0B3H,098H ;-1.17691E+07 DB 00AH,0DDH,047H,098H ; 1.30983E+07 DB 053H,0D1H,099H,099H ;-2-01612E+07 DB 00AH,01AH,09FH,098H ;-1.04269E+07 DB 065H,0BCH,0CDH,098H ;-1.34831E+07 DB 0D6H,077H,03EH,098H ; 1.24825E+07 DB 052H,0C7H,04FH,080H ; Last random number IN A,(0) ; INP (x) skeleton RET DB 1 ; POS (x) number (1) DB 255 ; Terminal width (255 = no auto CRLF) DB 28 ; Width for commas (3 columns) DB 0 ; No nulls after input bytes DB 0 ; Output enabled (^O off) DW 20 ; Initial lines counter DW 20 ; Initial lines number DW 0 ; Array load/save check sum DB 0 ; Break not by NMI DB 0 ; Break flag JP TTYLIN ; Input reflection (set to TTY) JP 0000H ; POINT reflection unused JP 0000H ; SET reflection JP 0000H ; RESET reflection DW STLOOK ; Temp string space DW -2 ; Current line number (cold) DW PROGST+1 ; Start of program text INITBE: ; ; END OF INITIALISATION TABLE --------------------------------------------------- ; ERRMSG: DB " Error",0 INMSG: DB " in ",0 ZERBYT EQU $-1 ; A zero byte OKMSG: DB "Ok",CR,LF,0,0 BRKMSG: DB "Break",0 ; BAKSTK: LD HL,4 ; Look for "FOR" block with ADD HL,SP ; same index as specified LOKFOR: LD A,(HL) ; Get block ID INC HL ; Point to index address CP ZFOR ; Is it a "FOR" token RET NZ ; No - exit LD C,(HL) ; BC = Address of "FOR" index INC HL LD B,(HL) INC HL ; Point to sign of STEP PUSH HL ; Save pointer to sign LD L,C ; HL = address of "FOR" index LD H,B LD A,D ; See if an index was specified OR E ; DE = 0 if no index specified EX DE,HL ; Specified index into HL JP Z,INDFND ; Skip if no index given EX DE,HL ; Index back into DE CALL CPDEHL ; Compare index with one given INDFND: LD BC,16-3 ; Offset to next block POP HL ; Restore pointer to sign RET Z ; Return if block found ADD HL,BC ; Point to next block JP LOKFOR ; Keep on looking ; MOVUP: CALL ENFMEM ; See if enough memory MOVSTR: PUSH BC ; Save end of source EX (SP),HL ; Swap source and dest" end POP BC ; Get end of destination MOVLP: CALL CPDEHL ; See if list moved LD A,(HL) ; Get byte LD (BC),A ; Move it RET Z ; Exit if all done DEC BC ; Next byte to move to DEC HL ; Next byte to move JP MOVLP ; Loop until all bytes moved ; CHKSTK: PUSH HL ; Save code string address LD HL,(ARREND) ; Lowest free memory LD B,0 ; BC = Number of levels to test ADD HL,BC ; 2 Bytes for each level ADD HL,BC DB 3EH ; Skip "PUSH HL" ENFMEM: PUSH HL ; Save code string address LD A,0D0H ; LOW -48; 48 Bytes minimum RAM SUB L LD L,A LD A,0FFH ; HIGH (-48); 48 Bytes minimum RAM SBC A,H JP C,OMERR ; Not enough - ?OM Error LD H,A ADD HL,SP ; Test if stack is overflowed POP HL ; Restore code string address RET C ; Return if enough mmory OMERR: LD E,OM ; ?OM Error JP ERROR ; DATSNR: LD HL,(DATLIN) ; Get line of current DATA item LD (LINEAT),HL ; Save as current line SNERR: LD E,SN ; ?SN Error DB 01H ; Skip "LD E,DZ" DZERR: LD E,DZ ; ?/0 Error DB 01H ; Skip "LD E,NF" NFERR: LD E,NF ; ?NF Error DB 01H ; Skip "LD E,RD" DDERR: LD E,RD ; ?DD Error DB 01H ; Skip "LD E,UF" UFERR: LD E,UF ; ?UF Error DB 01H ; Skip "LD E,OV OVERR: LD E,OV ; ?OV Error DB 01H ; Skip "LD E,TM" TMERR: LD E,TM ; ?TM Error ; ERROR: CALL CLREG ; Clear registers and stack LD (CTLOFG),A ; Enable output (A is 0) CALL STTLIN ; Start new line LD HL,ERRORS ; Point to error codes LD D,A ; D = 0 (A is 0) LD A,'?' CALL OUTC ; Output '?' ADD HL,DE ; Offset to correct error code LD A,(HL) ; First character CALL OUTC ; Output it CALL GETCHR ; Get next character CALL OUTC ; Output it LD HL,ERRMSG ; "Error" message ERRIN: CALL PRS ; Output message LD HL,(LINEAT) ; Get line of error LD DE,-2 ; Cold start error if -2 CALL CPDEHL ; See if cold start error JP Z,CSTART ; Cold start error - Restart LD A,H ; Was it a direct error? AND L ; Line = -1 if direct error INC A CALL NZ,LINEIN ; No - output line of error DB 3EH ; Skip "POP BC" POPNOK: POP BC ; Drop address in input buffer ; PRNTOK: XOR A ; Output "Ok" and get command LD (CTLOFG),A ; Enable output CALL STTLIN ; Start new line LD HL,OKMSG ; "Ok" message CALL PRS ; Output "Ok" GETCMD: LD HL,-1 ; Flag direct mode LD (LINEAT),HL ; Save as current line CALL GETLIN ; Get an input line JP C,GETCMD ; Get line again if break CALL GETCHR ; Get first character INC A ; Test if end of line DEC A ; Without affecting Carry JP Z,GETCMD ; Nothing entered - Get another PUSH AF ; Save Carry status CALL ATOH ; Get line number into DE PUSH DE ; Save line number CALL CRUNCH ; Tokenise rest of line LD B,A ; Length of tokenised line POP DE ; Restore line number POP AF ; Restore Carry JP NC,EXCUTE ; No line number - Direct mode PUSH DE ; Save line number PUSH BC ; Save length of tokenised line XOR A LD (LSTBIN),A ; Clear last byte input CALL GETCHR ; Get next character OR A ; Set flags PUSH AF ; And save them CALL SRCHLN ; Search for line number in DE JP C,LINFND ; Jump if line found POP AF ; Get status PUSH AF ; And re-save JP Z,ULERR ; Nothing after number - Error OR A ; Clear Carry LINFND: PUSH BC ; Save address of line in prog JP NC,INEWLN ; Line not found - Insert new EX DE,HL ; Next line address in DE LD HL,(PROGND) ; End of program SFTPRG: LD A,(DE) ; Shift rest of program down LD (BC),A INC BC ; Next destination INC DE ; Next source CALL CPDEHL ; All done? JP NZ,SFTPRG ; More to do LD H,B ; HL - New end of program LD L,C LD (PROGND),HL ; Update end of program ; INEWLN: POP DE ; Get address of line, POP AF ; Get status JP Z,SETPTR ; No text - Set up pointers LD HL,(PROGND) ; Get end of program EX (SP),HL ; Get length of input line POP BC ; End of program to BC ADD HL,BC ; Find new end PUSH HL ; Save new end CALL MOVUP ; Make space for line POP HL ; Restore new end LD (PROGND),HL ; Update end of program pointer EX DE,HL ; Get line to move up in HL LD (HL),H ; Save MSB POP DE ; Get new line number INC HL ; Skip pointer INC HL LD (HL),E ; Save LSB of line number INC HL LD (HL),D ; Save MSB of line number INC HL ; To first byte in line LD DE,BUFFER ; Copy buffer to program MOVBUF: LD A,(DE) ; Get source LD (HL),A ; Save destinations INC HL ; Next source INC DE ; Next destination OR A ; Done? JP NZ,MOVBUF ; No - Repeat SETPTR: CALL RUNFST ; Set line pointers INC HL ; To LSB of pointer EX DE,HL ; Address to DE PTRLP: LD H,D ; Address to HL LD L,E LD A,(HL) ; Get LSB of pointer INC HL ; To MSB of pointer OR (HL) ; Compare with MSB pointer JP Z,GETCMD ; Get command line if end INC HL ; To LSB of line number INC HL ; Skip line number INC HL ; Point to first byte in line XOR A ; Looking for 00 byte FNDEND: CP (HL) ; Found end of line? INC HL ; Move to next byte JP NZ,FNDEND ; No - Keep looking EX DE,HL ; Next line address to HL LD (HL),E ; Save LSB of pointer INC HL LD (HL),D ; Save MSB of pointer JP PTRLP ; Do next line ; SRCHLN: LD HL,(BASTXT) ; Start of program text SRCHLP: LD B,H ; BC = Address to look at LD C,L LD A,(HL) ; Get address of next line INC HL OR (HL) ; End of program found? DEC HL RET Z ; Yes - Line not found INC HL INC HL LD A,(HL) ; Get LSB of line number INC HL LD H,(HL) ; Get MSB of line number LD L,A CALL CPDEHL ; Compare with line in DE LD H,B ; HL = Start of this line LD L,C LD A,(HL) ; Get LSB of next line address INC HL LD H,(HL) ; Get MSB of next line address LD L,A ; Next line to HL CCF RET Z ; Lines found - Exit CCF RET NC ; Line not found,at line after JP SRCHLP ; Keep looking ; NEW: RET NZ ; Return if any more on line CLRPTR: LD HL,(BASTXT) ; Point to start of program XOR A ; Set program area to empty LD (HL),A ; Save LSB = 00 INC HL LD (HL),A ; Save MSB = 00 INC HL LD (PROGND),HL ; Set program end ; RUNFST: LD HL,(BASTXT) ; Clear all variables DEC HL ; INTVAR: LD (BRKLIN),HL ; Initialise RUN variables LD HL,(LSTRAM) ; Get end of RAM LD (STRBOT),HL ; Clear string space XOR A CALL RESTOR ; Reset DATA pointers LD HL,(PROGND) ; Get end of program LD (VAREND),HL ; Clear variables LD (ARREND),HL ; Clear arrays ; CLREG: POP BC ; Save return address LD HL,(STRSPC) ; Get end of working RAN LD SP,HL ; Set stack LD HL,TMSTPL ; Temporary string pool LD (TMSTPT),HL ; Reset temporary string ptr XOR A ; A = 00 LD L,A ; HL = 0000 LD H,A LD (CONTAD),HL ; No CONTinue LD (FORFLG),A ; Clear FOR flag LD (FNRGNM),HL ; Clear FN argument PUSH HL ; HL = 0000 PUSH BC ; Put back return DOAGN: LD HL,(BRKLIN) ; Get address of code to RUN RET ; Return to execution driver ; PROMPT: LD A,'?' ; '?' CALL OUTC ; Output character LD A,' ' ; Space CALL OUTC ; Output character JP RINPUT ; Get input line ; CRUNCH: XOR A ; Tokenise line @ HL to BUFFER LD (DATFLG),A ; Reset literal flag LD C,2+3 ; 2 byte number and 3 nulls LD DE,BUFFER ; Start of input buffer CRNCLP: LD A,(HL) ; Get byte CP ' ' ; Is it a space? JP Z,MOVDIR ; Yes - Copy direct LD B,A ; Save character CP '"' ; Is it a quote? JP Z,CPYLIT ; Yes - Copy literal string OR A ; Is it end of buffer? JP Z,ENDBUF ; Yes - End buffer LD A,(DATFLG) ; Get data type OR A ; Literal? LD A,(HL) ; Get byte to copy JP NZ,MOVDIR ; Literal - Copy direct CP '?' ; Is it '?' short for PRINT LD A,ZPRINT ; "PRINT" token JP Z,MOVDIR ; Yes - replace it LD A,(HL) ; Get byte again CP '0' ; Is it less than '0' JP C,FNDWRD ; Yes - Look for reserved words CP 60 ; ";"+1; Is it "0123456789:;" ? JP C,MOVDIR ; Yes - copy it direct FNDWRD: PUSH DE ; Look for reserved words LD DE,WORDS-1 ; Point to table PUSH BC ; Save count LD BC,RETNAD ; Where to return to PUSH BC ; Save return address LD B,ZEND-1 ; First token value -1 LD A,(HL) ; Get byte CP 'a' ; Less than 'a' ? JP C,SEARCH ; Yes - search for words CP 'z'+1 ; Greater than 'z' ? JP NC,SEARCH ; Yes - search for words AND 01011111B ; Force upper case LD (HL),A ; Replace byte SEARCH: LD C,(HL) ; Search for a word EX DE,HL GETNXT: INC HL ; Get next reserved word OR (HL) ; Start of word? JP P,GETNXT ; No - move on INC B ; Increment token value LD A, (HL) ; Get byte from table AND 01111111B ; Strip bit 7 RET Z ; Return if end of list CP C ; Same character as in buffer? JP NZ,GETNXT ; No - get next word EX DE,HL PUSH HL ; Save start of word ; NXTBYT: INC DE ; Look through rest of word LD A,(DE) ; Get byte from table OR A ; End of word ? JP M,MATCH ; Yes - Match found LD C,A ; Save it LD A,B ; Get token value CP ZGOTO ; Is it "GOTO" token ? JP NZ,NOSPC ; No - Don't allow spaces CALL GETCHR ; Get next character DEC HL ; Cancel increment from GETCHR NOSPC: INC HL ; Next byte LD A,(HL) ; Get byte CP 'a' ; Less than 'a' ? JP C,NOCHNG ; Yes - don't change AND 01011111B ; Make upper case NOCHNG: CP C ; Same as in buffer ? JP Z,NXTBYT ; Yes - keep testing POP HL ; Get back start of word JP SEARCH ; Look at next word ; MATCH: LD C,B ; Word found - Save token value POP AF ; Throw away return EX DE,HL RET ; Return to "RETNAD" RETNAD: EX DE,HL ; Get address in string LD A,C ; Get token value POP BC ; Restore buffer length POP DE ; Get destination address MOVDIR: INC HL ; Next source in buffer LD (DE),A ; Put byte in buffer INC DE ; Move up buffer INC C ; Increment length of buffer SUB ':' ; End of statement? JP Z,SETLIT ; Jump if multi-statement line CP ZDATA-3AH ; Is it DATA statement ? JP NZ,TSTREM ; No - see if REM SETLIT: LD (DATFLG),A ; Set literal flag TSTREM: SUB ZREM-3AH ; Is it REM? JP NZ,CRNCLP ; No - Leave flag LD B,A ; Copy rest of buffer NXTCHR: LD A,(HL) ; Get byte OR A ; End of line ? JP Z,ENDBUF ; Yes - Terminate buffer CP B ; End of statement ? JP Z,MOVDIR ; Yes - Get next one CPYLIT: INC HL ; Move up source string LD (DE),A ; Save in destination INC C ; Increment length INC DE ; Move up destination JP NXTCHR ; Repeat ; ENDBUF: LD HL,BUFFER-1 ; Point to start of buffer LD (DE),A ; Mark end of buffer (A = 00) INC DE LD (DE),A ; A = 00 INC DE LD (DE),A ; A = 00 RET ; DODEL: LD A,(NULFLG) ; Get null flag status OR A ; Is it zero? LD A,0 ; Zero A - Leave flags LD (NULFLG),A ; Zero null flag JP NZ,ECHDEL ; Set - Echo it DEC B ; Decrement length JP Z,GETLIN ; Get line again if empty CALL OUTC ; Output null character DB 3EH ; Skip "DEC B" ECHDEL: DEC B ; Count bytes in buffer DEC HL ; Back space buffer JP Z,OTKLN ; No buffer - Try again LD A,(HL) ; Get deleted byte CALL OUTC ; Echo it JP MORINP ; Get more input ; DELCHR: DEC B ; Count bytes in buffer DEC HL ; Back space buffer CALL OUTC ; Output character in A JP NZ,MORINP ; Not end - Get more OTKLN: CALL OUTC ; Output character in A KILIN: CALL PRCRLF ; Output CRLF JP TTYLIN ; Get line again ; GETLIN: TTYLIN: LD HL,BUFFER ; Get a line by character LD B,1 ; Set buffer as empty XOR A LD (NULFLG),A ; Clear null flag MORINP: CALL CLOTST ; Get character and test ^O LD C,A ; Save character in C CP DEL ; Delete character? JP Z,DODEL ; Yes - Process it LD A,(NULFLG) ; Get null flag OR A ; Test null flag status JP Z,PROCES ; Reset - Process character LD A,0 ; Set a null CALL OUTC ; Output null XOR A ; Clear A LD (NULFLG),A ; Reset null flag PROCES: LD A,C ; Get character CP CTRLG ; Bell? JP Z,PUTCTL ; Yes - Save it CP CTRLC ; Is it control "C"? CALL Z,PRCRLF ; Yes - Output CRLF SCF ; Flag break RET Z ; Return if control "C" CP CR ; Is it enter? JP Z,ENDINP ; Yes - Terminate input CP CTRLU ; Is it control "U"? JP Z,KILIN ; Yes - Get another line CP '@' ; Is it "kill line"? JP Z,OTKLN ; Yes - Kill line CP '_' ; Is it delete? JP Z,DELCHR ; Yes - Delete character CP BKSP ; Is it backspace? JP Z,DELCHR ; Yes - Delete character CP CTRLR ; Is it control "R"? JP NZ,PUTBUF ; No - Put in buffer PUSH BC ; Save buffer length PUSH DE ; Save DE PUSH HL ; Save buffer address LD (HL),0 ; Mark end of buffer CALL OUTNCR ; Output and do CRLF LD HL,BUFFER ; Point to buffer start CALL PRS ; Output buffer POP HL ; Restore buffer address POP DE ; Restore DE POP BC ; Restore buffer length JP MORINP ; Get another character ; PUTBUF: CP ' ' ; Is it a control code? JP C,MORINP ; Yes - Ignore PUTCTL: LD A,B ; Get number of bytes in buffer CP 72+1 ; Test for line overflow LD A,CTRLG ; Set a bell JP NC,OUTNBS ; Ring bell if buffer full LD A,C ; Get character LD (HL),C ; Save in buffer LD (LSTBIN),A ; Save last input byte INC HL ; Move up buffer INC B ; Increment length OUTIT: CALL OUTC ; Output the character entered JP MORINP ; Get another character ; OUTNBS: CALL OUTC ; Output bell and back over it LD A,BKSP ; Set back space JP OUTIT ; Output it and get more ; CPDEHL: LD A,H ; Get H SUB D ; Compare with D RET NZ ; Different - Exit LD A,L ; Get L SUB E ; Compare with E RET ; Return status ; CHKSYN: LD A,(HL) ; Check syntax of character EX (SP),HL ; Address of test byte CP (HL) ; Same as in code string? INC HL ; Return address EX (SP),HL ; Put it back JP Z,GETCHR ; Yes - Get next character JP SNERR ; Different - ?SN Error ; OUTC: PUSH AF ; Save character LD A,(CTLOFG) ; Get control "O" flag OR A ; Is it set? JP NZ,POPAF ; Yes - don't output POP AF ; Restore character PUSH BC ; Save buffer length PUSH AF ; Save character CP ' ' ; Is it a control code? JP C,DINPOS ; Yes - Don't INC POS(X) LD A,(LWIDTH) ; Get line width LD B,A ; To B LD A,(CURPOS) ; Get cursor position INC B ; Width 255? JP Z,INCLEN ; Yes - No width limit DEC B ; Restore width CP B ; At end of line? CALL Z,PRCRLF ; Yes - output CRLF INCLEN: INC A ; Move on one character LD (CURPOS),A ; Save new position DINPOS: POP AF ; Restore character POP BC ; Restore buffer length CALL MONOUT ; Send it RET ; CLOTST: CALL GETINP ; Get input character AND 01111111B ; Strip bit 7 CP CTRLO ; Is it control "O"? RET NZ ; No don't flip flag LD A,(CTLOFG) ; Get flag CPL ; Flip it LD (CTLOFG),A ; Put it back XOR A ; Null character RET ; LIST: CALL ATOH ; ASCII number to DE RET NZ ; Return if anything extra POP BC ; Rubbish - Not needed CALL SRCHLN ; Search for line number in DE PUSH BC ; Save address of line CALL SETLIN ; Set up lines counter LISTLP: POP HL ; Restore address of line LD C,(HL) ; Get LSB of next line INC HL LD B,(HL) ; Get MSB of next line INC HL LD A,B ; BC = 0 (End of program)? OR C JP Z,PRNTOK ; Yes - Go to command mode CALL COUNT ; Count lines CALL TSTBRK ; Test for break key PUSH BC ; Save address of next line CALL PRCRLF ; Output CRLF LD E,(HL) ; Get LSB of line number INC HL LD D,(HL) ; Get MSB of line number INC HL PUSH HL ; Save address of line start EX DE,HL ; Line number to HL CALL PRNTHL ; Output line number in decimal LD A,' ' ; Space after line number POP HL ; Restore start of line address LSTLP2: CALL OUTC ; Output character in A LSTLP3: LD A,(HL) ; Get next byte in line OR A ; End of line? INC HL ; To next byte in line JP Z,LISTLP ; Yes - get next line JP P,LSTLP2 ; No token - output it SUB ZEND-1 ; Find and output word LD C,A ; Token offset+1 to C LD DE,WORDS ; Reserved word list FNDTOK: LD A,(DE) ; Get character in list INC DE ; Move on to next OR A ; Is it start of word? JP P,FNDTOK ; No - Keep looking for word DEC C ; Count words JP NZ,FNDTOK ; Not there - keep looking OUTWRD: AND 01111111B ; Strip bit 7 CALL OUTC ; Output first character LD A,(DE) ; Get next character INC DE ; Move on to next OR A ; Is it end of word? JP P,OUTWRD ; No - output the rest JP LSTLP3 ; Next byte in line ; SETLIN: PUSH HL ; Set up LINES counter LD HL,(LINESN) ; Get LINES number LD (LINESC),HL ; Save in LINES counter POP HL RET ; COUNT: PUSH HL ; Save code string address PUSH DE LD HL,(LINESC) ; Get LINES counter LD DE,-1 ADC HL,DE ; Decrement LD (LINESC),HL ; Put it back POP DE POP HL ; Restore code string address RET P ; Return if more lines to go PUSH HL ; Save code string address LD HL,(LINESN) ; Get LINES number LD (LINESC),HL ; Reset LINES counter CALL GETINP ; Get input character CP CTRLC ; Is it control "C"? JP Z,RSLNBK ; Yes - Reset LINES and break POP HL ; Restore code string address JP COUNT ; Keep on counting ; RSLNBK: LD HL,(LINESN) ; Get LINES number LD (LINESC),HL ; Reset LINES counter JP BRKRET ; Go and output "Break" ; FOR: LD A,64H ; Flag "FOR" assignment LD (FORFLG),A ; Save "FOR" flag CALL LET ; Set up initial index POP BC ; Drop RETurn address PUSH HL ; Save code string address CALL DATA ; Get next statement address LD (LOOPST),HL ; Save it for start of loop LD HL,2 ; Offset for "FOR" block ADD HL,SP ; Point to it FORSLP: CALL LOKFOR ; Look for existing "FOR" block POP DE ; Get code string address JP NZ,FORFND ; No nesting found ADD HL,BC ; Move into "FOR" block PUSH DE ; Save code string address DEC HL LD D,(HL) ; Get MSB of loop statement DEC HL LD E,(HL) ; Get LSB of loop statement INC HL INC HL PUSH HL ; Save block address LD HL,(LOOPST) ; Get address of loop statement CALL CPDEHL ; Compare the FOR loops POP HL ; Restore block address JP NZ,FORSLP ; Different FORs - Find another POP DE ; Restore code string address LD SP,HL ; Remove all nested loops ; FORFND: EX DE,HL ; Code string address to HL LD C,8 CALL CHKSTK ; Check for 8 levels of stack PUSH HL ; Save code string address LD HL,(LOOPST) ; Get first statement of loop EX (SP),HL ; Save and restore code string PUSH HL ; Re-save code string address LD HL,(LINEAT) ; Get current line number EX (SP),HL ; Save and restore code string CALL TSTNUM ; Make sure it's a number CALL CHKSYN ; Make sure "TO" is next DB ZTO ; "TO" token CALL GETNUM ; Get "TO" expression value PUSH HL ; Save code string address CALL BCDEFP ; Move "TO" value to BCDE POP HL ; Restore code string address PUSH BC ; Save "TO" value in block PUSH DE LD BC,8100H ; BCDE - 1 (default STEP) LD D,C ; C=0 LD E,D ; D=0 LD A,(HL) ; Get next byte in code string CP ZSTEP ; See if "STEP" is stated LD A,1 ; Sign of step = 1 JP NZ,SAVSTP ; No STEP given - Default to 1 CALL GETCHR ; Jump over "STEP" token CALL GETNUM ; Get step value PUSH HL ; Save code string address CALL BCDEFP ; Move STEP to BCDE CALL TSTSGN ; Test sign of FPREG POP HL ; Restore code string address SAVSTP: PUSH BC ; Save the STEP value in block PUSH DE PUSH AF ; Save sign of STEP INC SP ; Don't save flags PUSH HL ; Save code string address LD HL,(BRKLIN) ; Get address of index variable EX (SP),HL ; Save and restore code string PUTFID: LD B,ZFOR ; "FOR" block marker PUSH BC ; Save it INC SP ; Don't save C ; RUNCNT: CALL TSTBRK ; Execution driver - Test break LD (BRKLIN),HL ; Save code address for break LD A,(HL) ; Get next byte in code string CP ':' ; Multi statement line? JP Z,EXCUTE ; Yes - Execute it OR A ; End of line? JP NZ,SNERR ; No - Syntax error INC HL ; Point to address of next line LD A,(HL) ; Get LSB of line pointer INC HL OR (HL) ; Is it zero (End of prog)? JP Z,ENDPRG ; Yes - Terminate execution INC HL ; Point to line number LD E,(HL) ; Get LSB of line number INC HL LD D,(HL) ; Get MSB of line number EX DE,HL ; Line number to HL LD (LINEAT),HL ; Save as current line number EX DE,HL ; Line number back to DE EXCUTE: CALL GETCHR ; Get key word LD DE,RUNCNT ; Where to RETurn to PUSH DE ; Save for RETurn IFJMP: RET Z ; Go to RUNCNT if end of STMT ONJMP: SUB ZEND ; Is it a token? JP C,LET ; No - try to assign it CP ZNEW+1-ZEND ; END to NEW ? JP NC,SNERR ; Not a key word - ?SN Error RLCA ; Double it LD C,A ; BC = Offset into table LD B,0 EX DE,HL ; Save code string address LD HL,WORDTB ; Keyword address table ADD HL,BC ; Point to routine address LD C,(HL) ; Get LSB of routine address INC HL LD B,(HL) ; Get MSB of routine address PUSH BC ; Save routine address EX DE,HL ; Restore code string address ; GETCHR: INC HL ; Point to next character LD A,(HL) ; Get next code string byte CP ':' ; Z if ':' RET NC ; NC if > "9" CP ' ' JP Z,GETCHR ; Skip over spaces CP '0' CCF ; NC if < '0' INC A ; Test for zero - Leave carry DEC A ; Z if Null RET ; RESTOR: EX DE,HL ; Save code string address LD HL,(BASTXT) ; Point to start of program JP Z,RESTNL ; Just RESTORE - reset pointer EX DE,HL ; Restore code string address CALL ATOH ; Get line number to DE PUSH HL ; Save code string address CALL SRCHLN ; Search for line number in DE LD H,B ; HL = Address of line LD L,C POP DE ; Restore code string address JP NC,ULERR ; ?UL Error if not found RESTNL: DEC HL ; Byte before DATA statement UPDATA: LD (NXTDAT),HL ; Update DATA pointer EX DE,HL ; Restore code string address RET ; TSTBRK: RST 18H ; Check input status RET Z ; No key, go back RST 10H ; Get the key into A CP ESC ; Escape key? JR Z,BRK ; Yes, break CP CTRLC ; JR Z,BRK ; Yes, break CP CTRLS ; Stop scrolling? RET NZ ; Other key, ignore ; STALL: RST 10H ; Wait for key CP CTRLQ ; Resume scrolling? RET Z ; Release the chokehold CP CTRLC ; Second break? JR Z,STOP ; Break during hold exits prog JR STALL ; Loop until or ; BRK LD A,0FFH ; Set BRKFLG LD (BRKFLG),A ; Store it ; STOP: RET NZ ; Exit if anything else DB 0F6H ; Flag "STOP" PEND: RET NZ ; Exit if anything else LD (BRKLIN),HL ; Save point of break DB 21H ; Skip "OR 11111111B" INPBRK: OR 11111111B ; Flag "Break" wanted POP BC ; Return not needed and more ENDPRG: LD HL,(LINEAT) ; Get current line number PUSH AF ; Save STOP / END status LD A,L ; Is it direct break? AND H INC A ; Line is -1 if direct break JP Z,NOLIN ; Yes - No line number LD (ERRLIN),HL ; Save line of break LD HL,(BRKLIN) ; Get point of break LD (CONTAD),HL ; Save point to CONTinue NOLIN: XOR A LD (CTLOFG),A ; Enable output CALL STTLIN ; Start a new line POP AF ; Restore STOP / END status LD HL,BRKMSG ; "Break" message JP NZ,ERRIN ; "in line" wanted? JP PRNTOK ; Go to command mode ; CONT: LD HL,(CONTAD) ; Get CONTinue address LD A,H ; Is it zero? OR L LD E,CN ; ?CN Error JP Z,ERROR ; Yes - output "?CN Error" EX DE,HL ; Save code string address LD HL,(ERRLIN) ; Get line of last break LD (LINEAT),HL ; Set up current line number EX DE,HL ; Restore code string address RET ; CONTinue where left off ; NULL: CALL GETINT ; Get integer 0-255 RET NZ ; Return if bad value LD (NULLS),A ; Set nulls number RET ; ACCSUM: PUSH HL ; Save address in array LD HL,(CHKSUM) ; Get check sum LD B,0 ; BC - Value of byte LD C,A ADD HL,BC ; Add byte to check sum LD (CHKSUM),HL ; Re-save check sum POP HL ; Restore address in array RET ; CHKLTR: LD A,(HL) ; Get byte CP 'A' ; < 'a' ? RET C ; Carry set if not letter CP 'Z'+1 ; > 'z' ? CCF RET ; Carry set if not letter ; FPSINT: CALL GETCHR ; Get next character POSINT: CALL GETNUM ; Get integer 0 to 32767 DEPINT: CALL TSTSGN ; Test sign of FPREG JP M,FCERR ; Negative - ?FC Error DEINT: LD A,(FPEXP) ; Get integer value to DE CP 80H+16 ; Exponent in range (16 bits)? JP C,FPINT ; Yes - convert it LD BC,9080H ; BCDE = -32768 LD DE,0000 PUSH HL ; Save code string address CALL CMPNUM ; Compare FPREG with BCDE POP HL ; Restore code string address LD D,C ; MSB to D RET Z ; Return if in range FCERR: LD E,FC ; ?FC Error JP ERROR ; Output error- ; ATOH: DEC HL ; ASCII number to DE binary GETLN: LD DE,0 ; Get number to DE GTLNLP: CALL GETCHR ; Get next character RET NC ; Exit if not a digit PUSH HL ; Save code string address PUSH AF ; Save digit LD HL,65529/10 ; Largest number 65529 CALL CPDEHL ; Number in range? JP C,SNERR ; No - ?SN Error LD H,D ; HL = Number LD L,E ADD HL,DE ; Times 2 ADD HL,HL ; Times 4 ADD HL,DE ; Times 5 ADD HL,HL ; Times 10 POP AF ; Restore digit SUB '0' ; Make it 0 to 9 LD E,A ; DE = Value of digit LD D,0 ADD HL,DE ; Add to number EX DE,HL ; Number to DE POP HL ; Restore code string address JP GTLNLP ; Go to next character ; CLEAR: JP Z,INTVAR ; Just "CLEAR" Keep parameters CALL POSINT ; Get integer 0 to 32767 to DE DEC HL ; Cancel increment CALL GETCHR ; Get next character PUSH HL ; Save code string address LD HL,(LSTRAM) ; Get end of RAM JP Z,STORED ; No value given - Use stored POP HL ; Restore code string address CALL CHKSYN ; Check for comma DB ',' PUSH DE ; Save number CALL POSINT ; Get integer 0 to 32767 DEC HL ; Cancel increment CALL GETCHR ; Get next character JP NZ,SNERR ; ?SN Error if more on line EX (SP),HL ; Save code string address EX DE,HL ; Number to DE STORED: LD A,L ; Get LSB of new RAM top SUB E ; Subtract LSB of string space LD E,A ; Save LSB LD A,H ; Get MSB of new RAM top SBC A,D ; Subtract MSB of string space LD D,A ; Save MSB JP C,OMERR ; ?OM Error if not enough mem PUSH HL ; Save RAM top LD HL,(PROGND) ; Get program end LD BC,40 ; 40 Bytes minimum working RAM ADD HL,BC ; Get lowest address CALL CPDEHL ; Enough memory? JP NC,OMERR ; No - ?OM Error EX DE,HL ; RAM top to HL LD (STRSPC),HL ; Set new string space POP HL ; End of memory to use LD (LSTRAM),HL ; Set new top of RAM POP HL ; Restore code string address JP INTVAR ; Initialise variables ; RUN: JP Z,RUNFST ; RUN from start if just RUN CALL INTVAR ; Initialise variables LD BC,RUNCNT ; Execution driver loop JP RUNLIN ; RUN from line number ; GOSUB: LD C,3 ; 3 Levels of stack needed CALL CHKSTK ; Check for 3 levels of stack POP BC ; Get return address PUSH HL ; Save code string for RETURN PUSH HL ; And for GOSUB routine LD HL,(LINEAT) ; Get current line EX (SP),HL ; Into stack - Code string out LD A,ZGOSUB ; "GOSUB" token PUSH AF ; Save token INC SP ; Don't save flags ; RUNLIN: PUSH BC ; Save return address GOTO: CALL ATOH ; ASCII number to DE binary CALL REM ; Get end of line PUSH HL ; Save end of line LD HL,(LINEAT) ; Get current line CALL CPDEHL ; Line after current? POP HL ; Restore end of line INC HL ; Start of next line CALL C,SRCHLP ; Line is after current line CALL NC,SRCHLN ; Line is before current line LD H,B ; Set up code string address LD L,C DEC HL ; Incremented after RET C ; Line found ULERR: LD E,UL ; ?UL Error JP ERROR ; Output error message ; RETURN: RET NZ ; Return if not just RETURN LD D,-1 ; Flag "GOSUB" search CALL BAKSTK ; Look "GOSUB" block LD SP,HL ; Kill all FORs in subroutine CP ZGOSUB ; Test for "GOSUB" token LD E,RG ; ?RG Error JP NZ,ERROR ; Error if no "GOSUB" found POP HL ; Get RETURN line number LD (LINEAT),HL ; Save as current INC HL ; Was it from direct statement? LD A,H OR L ; Return to line JP NZ,RETLIN ; No - Return to line LD A,(LSTBIN) ; Any INPUT in subroutine? OR A ; If so buffer is corrupted JP NZ,POPNOK ; Yes - Go to command mode RETLIN: LD HL,RUNCNT ; Execution driver loop EX (SP),HL ; Into stack - Code string out DB 3EH ; Skip "POP HL" NXTDTA: POP HL ; Restore code string address ; DATA: DB 01H,3AH ; ':' End of statement REM: LD C,0 ; 00 End of statement LD B,0 NXTSTL: LD A,C ; Statement and byte LD C,B LD B,A ; Statement end byte NXTSTT: LD A,(HL) ; Get byte OR A ; End of line? RET Z ; Yes - Exit CP B ; End of statement? RET Z ; Yes - Exit INC HL ; Next byte CP '"' ; Literal string? JP Z,NXTSTL ; Yes - Look for another '"' JP NXTSTT ; Keep looking ; LET: CALL GETVAR ; Get variable name CALL CHKSYN ; Make sure "=" follows DB ZEQUAL ; "=" token PUSH DE ; Save address of variable LD A,(TYPE) ; Get data type PUSH AF ; Save type CALL EVAL ; Evaluate expression POP AF ; Restore type EX (SP),HL ; Save code - Get var addr LD (BRKLIN),HL ; Save address of variable RRA ; Adjust type CALL CHKTYP ; Check types are the same JP Z,LETNUM ; Numeric - Move value LETSTR: PUSH HL ; Save address of string var LD HL,(FPREG) ; Pointer to string entry PUSH HL ; Save it on stack INC HL ; Skip over length INC HL LD E,(HL) ; LSB of string address INC HL LD D,(HL) ; MSB of string address LD HL,(BASTXT) ; Point to start of program CALL CPDEHL ; Is string before program? JP NC,CRESTR ; Yes - Create string entry LD HL,(STRSPC) ; Point to string space CALL CPDEHL ; Is string literal in program? POP DE ; Restore address of string JP NC,MVSTPT ; Yes - Set up pointer LD HL,TMPSTR ; Temporary string pool CALL CPDEHL ; Is string in temporary pool? JP NC,MVSTPT ; No - Set up pointer DB 3EH ; Skip "POP DE" CRESTR: POP DE ; Restore address of string CALL BAKTMP ; Back to last tmp-str entry EX DE,HL ; Address of string entry CALL SAVSTR ; Save string in string area MVSTPT: CALL BAKTMP ; Back to last tmp-str entry POP HL ; Get string pointer CALL DETHL4 ; Move string pointer to var POP HL ; Restore code string address RET ; LETNUM: PUSH HL ; Save address of variable CALL FPTHL ; Move value to variable POP DE ; Restore address of variable POP HL ; Restore code string address RET ; ON: CALL GETINT ; Get integer 0-255 LD A,(HL) ; Get "GOTO" or "GOSUB" token LD B,A ; Save in B CP ZGOSUB ; "GOSUB" token? JP Z,ONGO ; Yes - Find line number CALL CHKSYN ; Make sure it's "GOTO" DB ZGOTO ; "GOTO" token DEC HL ; Cancel increment ONGO: LD C,E ; Integer of branch value ONGOLP: DEC C ; Count branches LD A,B ; Get "GOTO" or "GOSUB" token JP Z,ONJMP ; Go to that line if right one CALL GETLN ; Get line number to DE CP ',' ; Another line number? RET NZ ; No - Drop through JP ONGOLP ; Yes - loop ; IF: CALL EVAL ; Evaluate expression LD A,(HL) ; Get token CP ZGOTO ; "GOTO" token? JP Z,IFGO ; Yes - Get line CALL CHKSYN ; Make sure it's "THEN" DB ZTHEN ; "THEN" token DEC HL ; Cancel increment IFGO: CALL TSTNUM ; Make sure it's numeric CALL TSTSGN ; Test state of expression JP Z,REM ; False - Drop through CALL GETCHR ; Get next character JP C,GOTO ; Number - GOTO that line JP IFJMP ; Otherwise do statement ; MRPRNT: DEC HL ; DEC 'cos GETCHR INCs CALL GETCHR ; Get next character PRINT: JP Z,PRCRLF ; CRLF if just PRINT PRNTLP: RET Z ; End of list - Exit CP ZTAB ; "TAB(" token? JP Z,DOTAB ; Yes - Do TAB routine CP ZSPC ; "SPC(" token? JP Z,DOTAB ; Yes - Do SPC routine PUSH HL ; Save code string address CP ',' ; Comma? JP Z,DOCOM ; Yes - Move to next zone CP 59;";" ; Semi-colon? JP Z,NEXITM ; Do semi-colon routine POP BC ; Code string address to BC CALL EVAL ; Evaluate expression PUSH HL ; Save code string address LD A,(TYPE) ; Get variable type OR A ; Is it a string variable? JP NZ,PRNTST ; Yes - Output string contents CALL NUMASC ; Convert number to text CALL CRTST ; Create temporary string LD (HL),' ' ; Followed by a space LD HL,(FPREG) ; Get length of output INC (HL) ; Plus 1 for the space LD HL,(FPREG) ; < Not needed > LD A,(LWIDTH) ; Get width of line LD B,A ; To B INC B ; Width 255 (No limit)? JP Z,PRNTNB ; Yes - Output number string INC B ; Adjust it LD A,(CURPOS) ; Get cursor position ADD A,(HL) ; Add length of string DEC A ; Adjust it CP B ; Will output fit on this line? CALL NC,PRCRLF ; No - CRLF first PRNTNB: CALL PRS1 ; Output string at (HL) XOR A ; Skip CALL by setting 'z' flag PRNTST: CALL NZ,PRS1 ; Output string at (HL) POP HL ; Restore code string address JP MRPRNT ; See if more to PRINT ; STTLIN: LD A,(CURPOS) ; Make sure on new line OR A ; Already at start? RET Z ; Yes - Do nothing JP PRCRLF ; Start a new line ; ENDINP: LD (HL),0 ; Mark end of buffer LD HL,BUFFER-1 ; Point to buffer PRCRLF: LD A,CR ; Load a CR CALL OUTC ; Output character LD A,LF ; Load a LF CALL OUTC ; Output character DONULL: XOR A ; Set to position 0 LD (CURPOS),A ; Store it LD A,(NULLS) ; Get number of nulls NULLP: DEC A ; Count them RET Z ; Return if done PUSH AF ; Save count XOR A ; Load a null CALL OUTC ; Output it POP AF ; Restore count JP NULLP ; Keep counting ; DOCOM: LD A,(COMMAN) ; Get comma width LD B,A ; Save in B LD A,(CURPOS) ; Get current position CP B ; Within the limit? CALL NC,PRCRLF ; No - output CRLF JP NC,NEXITM ; Get next item ZONELP: SUB 14 ; Next zone of 14 characters JP NC,ZONELP ; Repeat if more zones CPL ; Number of spaces to output JP ASPCS ; Output them ; DOTAB: PUSH AF ; Save token CALL FNDNUM ; Evaluate expression CALL CHKSYN ; Make sure ")" follows DB ")" DEC HL ; Back space on to ")" POP AF ; Restore token SUB ZSPC ; Was it "SPC(" ? PUSH HL ; Save code string address JP Z,DOSPC ; Yes - Do 'E' spaces LD A,(CURPOS) ; Get current position DOSPC: CPL ; Number of spaces to print to ADD A,E ; Total number to print JP NC,NEXITM ; TAB < Current POS(X) ASPCS: INC A ; Output A spaces LD B,A ; Save number to print LD A,' ' ; Space SPCLP: CALL OUTC ; Output character in A DEC B ; Count them JP NZ,SPCLP ; Repeat if more NEXITM: POP HL ; Restore code string address CALL GETCHR ; Get next character JP PRNTLP ; More to print ; REDO: DB "?Redo from start",CR,LF,0 ; BADINP: LD A,(READFG) ; READ or INPUT? OR A JP NZ,DATSNR ; READ - ?SN Error POP BC ; Throw away code string addr LD HL,REDO ; "Redo from start" message CALL PRS ; Output string JP DOAGN ; Do last INPUT again ; INPUT: CALL IDTEST ; Test for illegal direct LD A,(HL) ; Get character after "INPUT" CP '"' ; Is there a prompt string? LD A,0 ; Clear A and leave flags LD (CTLOFG),A ; Enable output JP NZ,NOPMPT ; No prompt - get input CALL QTSTR ; Get string terminated by '"' CALL CHKSYN ; Check for ';' after prompt DB ';' PUSH HL ; Save code string address CALL PRS1 ; Output prompt string DB 3EH ; Skip "PUSH HL" NOPMPT: PUSH HL ; Save code string address CALL PROMPT ; Get input with "? " prompt POP BC ; Restore code string address JP C,INPBRK ; Break pressed - Exit INC HL ; Next byte LD A,(HL) ; Get it OR A ; End of line? DEC HL ; Back again PUSH BC ; Re-save code string address JP Z,NXTDTA ; Yes - Find next DATA stmt LD (HL),',' ; Store comma as separator JP NXTITM ; Get next item ; READ: PUSH HL ; Save code string address LD HL,(NXTDAT) ; Next DATA statement DB 0F6H ; Flag "READ" NXTITM: XOR A ; Flag "INPUT" LD (READFG),A ; Save "READ"/"INPUT" flag EX (SP),HL ; Get code str' , Save pointer JP GTVLUS ; Get values ; NEDMOR: CALL CHKSYN ; Check for comma between items DB ',' GTVLUS: CALL GETVAR ; Get variable name EX (SP),HL ; Save code str" , Get pointer PUSH DE ; Save variable address LD A,(HL) ; Get next "INPUT"/"DATA" byte CP ',' ; Comma? JP Z,ANTVLU ; Yes - Get another value LD A,(READFG) ; Is it READ? OR A JP NZ,FDTLP ; Yes - Find next DATA stmt LD A,'?' ; More INPUT needed CALL OUTC ; Output character CALL PROMPT ; Get INPUT with prompt POP DE ; Variable address POP BC ; Code string address JP C,INPBRK ; Break pressed INC HL ; Point to next DATA byte LD A,(HL) ; Get byte OR A ; Is it zero (No input) ? DEC HL ; Back space INPUT pointer PUSH BC ; Save code string address JP Z,NXTDTA ; Find end of buffer PUSH DE ; Save variable address ANTVLU: LD A,(TYPE) ; Check data type OR A ; Is it numeric? JP Z,INPBIN ; Yes - Convert to binary CALL GETCHR ; Get next character LD D,A ; Save input character LD B,A ; Again CP '"' ; Start of literal sting? JP Z,STRENT ; Yes - Create string entry LD A,(READFG) ; "READ" or "INPUT" ? OR A LD D,A ; Save 00 if "INPUT" JP Z,ITMSEP ; "INPUT" - End with 00 LD D,':' ; "DATA" - End with 00 or ':' ITMSEP: LD B,',' ; Item separator DEC HL ; Back space for DTSTR STRENT: CALL DTSTR ; Get string terminated by D EX DE,HL ; String address to DE LD HL,LTSTND ; Where to go after LETSTR EX (SP),HL ; Save HL , get input pointer PUSH DE ; Save address of string JP LETSTR ; Assign string to variable ; INPBIN: CALL GETCHR ; Get next character CALL ASCTFP ; Convert ASCII to FP number EX (SP),HL ; Save input ptr, Get var addr CALL FPTHL ; Move FPREG to variable POP HL ; Restore input pointer LTSTND: DEC HL ; DEC 'cos GETCHR INCs CALL GETCHR ; Get next character JP Z,MORDT ; End of line - More needed? CP ',' ; Another value? JP NZ,BADINP ; No - Bad input MORDT: EX (SP),HL ; Get code string address DEC HL ; DEC 'cos GETCHR INCs CALL GETCHR ; Get next character JP NZ,NEDMOR ; More needed - Get it POP DE ; Restore DATA pointer LD A,(READFG) ; "READ" or "INPUT" ? OR A EX DE,HL ; DATA pointer to HL JP NZ,UPDATA ; Update DATA pointer if "READ" PUSH DE ; Save code string address OR (HL) ; More input given? LD HL,EXTIG ; "?Extra ignored" message CALL NZ,PRS ; Output string if extra given POP HL ; Restore code string address RET ; EXTIG: DB "?Extra ignored",CR,LF,0 ; FDTLP: CALL DATA ; Get next statement OR A ; End of line? JP NZ,FANDT ; No - See if DATA statement INC HL LD A,(HL) ; End of program? INC HL OR (HL) ; 00 00 Ends program LD E,OD ; ?OD Error JP Z,ERROR ; Yes - Out of DATA INC HL LD E,(HL) ; LSB of line number INC HL LD D,(HL) ; MSB of line number EX DE,HL LD (DATLIN),HL ; Set line of current DATA item EX DE,HL FANDT: CALL GETCHR ; Get next character CP ZDATA ; "DATA" token JP NZ,FDTLP ; No "DATA" - Keep looking JP ANTVLU ; Found - Convert input ; NEXT: LD DE,0 ; In case no index given NEXT1: CALL NZ,GETVAR ; Get index address LD (BRKLIN),HL ; Save code string address CALL BAKSTK ; Look for "FOR" block JP NZ,NFERR ; No "FOR" - ?NF Error LD SP,HL ; Clear nested loops PUSH DE ; Save index address LD A,(HL) ; Get sign of STEP INC HL PUSH AF ; Save sign of STEP PUSH DE ; Save index address CALL PHLTFP ; Move index value to FPREG EX (SP),HL ; Save address of TO value PUSH HL ; Save address of index CALL ADDPHL ; Add STEP to index value POP HL ; Restore address of index CALL FPTHL ; Move value to index variable POP HL ; Restore address of TO value CALL LOADFP ; Move TO value to BCDE PUSH HL ; Save address of line of FOR CALL CMPNUM ; Compare index with TO value POP HL ; Restore address of line num POP BC ; Address of sign of STEP SUB B ; Compare with expected sign CALL LOADFP ; BC = Loop stmt,DE = Line num JP Z,KILFOR ; Loop finished - Terminate it EX DE,HL ; Loop statement line number LD (LINEAT),HL ; Set loop line number LD L,C ; Set code string to loop LD H,B JP PUTFID ; Put back "FOR" and continue ; KILFOR: LD SP,HL ; Remove "FOR" block LD HL,(BRKLIN) ; Code string after "NEXT" LD A,(HL) ; Get next byte in code string CP ',' ; More NEXTs ? JP NZ,RUNCNT ; No - Do next statement CALL GETCHR ; Position to index name CALL NEXT1 ; Re-enter NEXT routine ; < will not RETurn to here , Exit to RUNCNT or Loop > ; GETNUM: CALL EVAL ; Get a numeric expression TSTNUM: DB 0F6H ; Clear carry (numeric) TSTSTR: SCF ; Set carry (string) CHKTYP: LD A,(TYPE) ; Check types match ADC A,A ; Expected + actual OR A ; Clear carry , set parity RET PE ; Even parity - Types match JP TMERR ; Different types - Error ; OPNPAR: CALL CHKSYN ; Make sure "(" follows DB "(" EVAL: DEC HL ; Evaluate expression & save LD D,0 ; Precedence value EVAL1: PUSH DE ; Save precedence LD C,1 CALL CHKSTK ; Check for 1 level of stack CALL OPRND ; Get next expression value EVAL2: LD (NXTOPR),HL ; Save address of next operator EVAL3: LD HL,(NXTOPR) ; Restore address of next opr POP BC ; Precedence value and operator LD A,B ; Get precedence value CP 78H ; "AND" or "OR" ? CALL NC,TSTNUM ; No - Make sure it's a number LD A,(HL) ; Get next operator / function LD D,0 ; Clear Last relation RLTLP: SUB ZGTR ; ">" Token JP C,FOPRND ; + - * / ^ AND OR - Test it CP ZLTH+1-ZGTR ; < = > JP NC,FOPRND ; Function - Call it CP ZEQUAL-ZGTR ; "=" RLA ; <- Test for legal XOR D ; <- combinations of < = > CP D ; <- by combining last token LD D,A ; <- with current one JP C,SNERR ; Error if "<<' '==" or ">>" LD (CUROPR),HL ; Save address of current token CALL GETCHR ; Get next character JP RLTLP ; Treat the two as one ; FOPRND: LD A,D ; < = > found ? OR A JP NZ,TSTRED ; Yes - Test for reduction LD A,(HL) ; Get operator token LD (CUROPR),HL ; Save operator address SUB ZPLUS ; Operator or function? RET C ; Neither - Exit CP ZOR+1-ZPLUS ; Is it + - * / ^ AND OR ? RET NC ; No - Exit LD E,A ; Coded operator LD A,(TYPE) ; Get data type DEC A ; FF = numeric , 00 = string OR E ; Combine with coded operator LD A,E ; Get coded operator JP Z,CONCAT ; String concatenation RLCA ; Times 2 ADD A,E ; Times 3 LD E,A ; To DE (D is 0) LD HL,PRITAB ; Precedence table ADD HL,DE ; To the operator concerned LD A,B ; Last operator precedence LD D,(HL) ; Get evaluation precedence CP D ; Compare with eval precedence RET NC ; Exit if higher precedence INC HL ; Point to routine address CALL TSTNUM ; Make sure it's a number ; STKTHS: PUSH BC ; Save last precedence & token LD BC,EVAL3 ; Where to go on prec' break PUSH BC ; Save on stack for return LD B,E ; Save operator LD C,D ; Save precedence CALL STAKFP ; Move value to stack LD E,B ; Restore operator LD D,C ; Restore precedence LD C,(HL) ; Get LSB of routine address INC HL LD B,(HL) ; Get MSB of routine address INC HL PUSH BC ; Save routine address LD HL,(CUROPR) ; Address of current operator JP EVAL1 ; Loop until prec' break ; OPRND: XOR A ; Get operand routine LD (TYPE),A ; Set numeric expected CALL GETCHR ; Get next character LD E,MO ; ?MO Error JP Z,ERROR ; No operand - Error JP C,ASCTFP ; Number - Get value CALL CHKLTR ; See if a letter JP NC,CONVAR ; Letter - Find variable CP '&' ; &H = HEX, &B = BINARY JR NZ, NOTAMP CALL GETCHR ; Get next character CP 'H' ; Hex number indicated? [function added] JP Z,HEXTFP ; Convert Hex to FPREG CP 'B' ; Binary number indicated? [function added] JP Z,BINTFP ; Convert Bin to FPREG LD E,SN ; If neither then a ?SN Error JP Z,ERROR NOTAMP: CP ZPLUS ; '+' Token ? JP Z,OPRND ; Yes - Look for operand CP '.' ; '.' ? JP Z,ASCTFP ; Yes - Create FP number CP ZMINUS ; '-' Token ? JP Z,MINUS ; Yes - Do minus CP '"' ; Literal string ? JP Z,QTSTR ; Get string terminated by '"' CP ZNOT ; "NOT" Token ? JP Z,EVNOT ; Yes - Eval NOT expression CP ZFN ; "FN" Token ? JP Z,DOFN ; Yes - Do FN routine SUB ZSGN ; Is it a function? JP NC,FNOFST ; Yes - Evaluate function EVLPAR: CALL OPNPAR ; Evaluate expression in "()" CALL CHKSYN ; Make sure ")" follows DB ")" RET ; MINUS: LD D,7DH ; '-' precedence CALL EVAL1 ; Evaluate until prec' break LD HL,(NXTOPR) ; Get next operator address PUSH HL ; Save next operator address CALL INVSGN ; Negate value RETNUM: CALL TSTNUM ; Make sure it's a number POP HL ; Restore next operator address RET ; CONVAR: CALL GETVAR ; Get variable address to DE FRMEVL: PUSH HL ; Save code string address EX DE,HL ; Variable address to HL LD (FPREG),HL ; Save address of variable LD A,(TYPE) ; Get type OR A ; Numeric? CALL Z,PHLTFP ; Yes - Move contents to FPREG POP HL ; Restore code string address RET ; FNOFST: LD B,0 ; Get address of function RLCA ; Double function offset LD C,A ; BC = Offset in function table PUSH BC ; Save adjusted token value CALL GETCHR ; Get next character LD A,C ; Get adjusted token value CP 2*(ZLEFT-ZSGN)-1; Adj' LEFT$,RIGHT$ or MID$ ? JP C,FNVAL ; No - Do function CALL OPNPAR ; Evaluate expression (X,... CALL CHKSYN ; Make sure ',' follows DB ',' CALL TSTSTR ; Make sure it's a string EX DE,HL ; Save code string address LD HL,(FPREG) ; Get address of string EX (SP),HL ; Save address of string PUSH HL ; Save adjusted token value EX DE,HL ; Restore code string address CALL GETINT ; Get integer 0-255 EX DE,HL ; Save code string address EX (SP),HL ; Save integer,HL = adj' token JP GOFUNC ; Jump to string function ; FNVAL: CALL EVLPAR ; Evaluate expression EX (SP),HL ; HL = Adjusted token value LD DE,RETNUM ; Return number from function PUSH DE ; Save on stack GOFUNC: LD BC,FNCTAB ; Function routine addresses ADD HL,BC ; Point to right address LD C,(HL) ; Get LSB of address INC HL ; LD H,(HL) ; Get MSB of address LD L,C ; Address to HL JP (HL) ; Jump to function ; SGNEXP: DEC D ; Dee to flag negative exponent CP ZMINUS ; '-' token ? RET Z ; Yes - Return CP '-' ; '-' ASCII ? RET Z ; Yes - Return INC D ; Inc to flag positive exponent CP '+' ; '+' ASCII ? RET Z ; Yes - Return CP ZPLUS ; '+' token ? RET Z ; Yes - Return DEC HL ; DEC 'cos GETCHR INCs RET ; Return "NZ" ; POR: DB 0F6H ; Flag "OR" PAND: XOR A ; Flag "AND" PUSH AF ; Save "AND" / "OR" flag CALL TSTNUM ; Make sure it's a number CALL DEINT ; Get integer -32768 to 32767 POP AF ; Restore "AND" / "OR" flag EX DE,HL ; <- Get last POP BC ; <- value EX (SP),HL ; <- from EX DE,HL ; <- stack CALL FPBCDE ; Move last value to FPREG PUSH AF ; Save "AND" / "OR" flag CALL DEINT ; Get integer -32768 to 32767 POP AF ; Restore "AND" / "OR" flag POP BC ; Get value LD A,C ; Get LSB LD HL,ACPASS ; Address of save AC as current JP NZ,POR1 ; Jump if OR AND E ; "AND" LSBs LD C,A ; Save LSB LD A,B ; Get MBS AND D ; "AND" MSBs JP (HL) ; Save AC as current (ACPASS) ; POR1: OR E ; "OR" LSBs LD C,A ; Save LSB LD A,B ; Get MSB OR D ; "OR" MSBs JP (HL) ; Save AC as current (ACPASS) ; TSTRED: LD HL,CMPLOG ; Logical compare routine LD A,(TYPE) ; Get data type RRA ; Carry set = string LD A,D ; Get last precedence value RLA ; Times 2 plus carry LD E,A ; To E LD D,64H ; Relational precedence LD A,B ; Get current precedence CP D ; Compare with last RET NC ; Eval if last was rel' or log' JP STKTHS ; Stack this one and get next ; CMPLOG: DW CMPLG1 ; Compare two values / strings CMPLG1: LD A,C ; Get data type OR A RRA POP BC ; Get last expression to BCDE POP DE PUSH AF ; Save status CALL CHKTYP ; Check that types match LD HL,CMPRES ; Result to comparison PUSH HL ; Save for RETurn JP Z,CMPNUM ; Compare values if numeric XOR A ; Compare two strings LD (TYPE),A ; Set type to numeric PUSH DE ; Save string name CALL GSTRCU ; Get current string LD A,(HL) ; Get length of string INC HL INC HL LD C,(HL) ; Get LSB of address INC HL LD B,(HL) ; Get MSB of address POP DE ; Restore string name PUSH BC ; Save address of string PUSH AF ; Save length of string CALL GSTRDE ; Get second string CALL LOADFP ; Get address of second string POP AF ; Restore length of string 1 LD D,A ; Length to D POP HL ; Restore address of string 1 CMPSTR: LD A,E ; Bytes of string 2 to do OR D ; Bytes of string 1 to do RET Z ; Exit if all bytes compared LD A,D ; Get bytes of string 1 to do SUB 1 RET C ; Exit if end of string 1 XOR A CP E ; Bytes of string 2 to do INC A RET NC ; Exit if end of string 2 DEC D ; Count bytes in string 1 DEC E ; Count bytes in string 2 LD A,(BC) ; Byte in string 2 CP (HL) ; Compare to byte in string 1 INC HL ; Move up string 1 INC BC ; Move up string 2 JP Z,CMPSTR ; Same - Try next bytes CCF ; Flag difference (">" or "<") JP FLGDIF ; "<" gives -1 , ">" gives +1 ; CMPRES: INC A ; Increment current value ADC A,A ; Double plus carry POP BC ; Get other value AND B ; Combine them ADD A,-1 ; Carry set if different SBC A,A ; 00 - Equal , FF - Different JP FLGREL ; Set current value & continue ; EVNOT: LD D,5AH ; Precedence value for "NOT" CALL EVAL1 ; Eval until precedence break CALL TSTNUM ; Make sure it's a number CALL DEINT ; Get integer -32768 - 32767 LD A,E ; Get LSB CPL ; Invert LSB LD C,A ; Save "NOT" of LSB LD A,D ; Get MSB CPL ; Invert MSB CALL ACPASS ; Save AC as current POP BC ; Clean up stack JP EVAL3 ; Continue evaluation ; DIMRET: DEC HL ; DEC 'cos GETCHR INCs CALL GETCHR ; Get next character RET Z ; End of DIM statement CALL CHKSYN ; Make sure ',' follows DB ',' DIM: LD BC,DIMRET ; Return to "DIMRET" PUSH BC ; Save on stack DB 0F6H ; Flag "Create" variable GETVAR: XOR A ; Find variable address,to DE LD (LCRFLG),A ; Set locate / create flag LD B,(HL) ; Get First byte of name GTFNAM: CALL CHKLTR ; See if a letter JP C,SNERR ; ?SN Error if not a letter XOR A LD C,A ; Clear second byte of name LD (TYPE),A ; Set type to numeric CALL GETCHR ; Get next character JP C,SVNAM2 ; Numeric - Save in name CALL CHKLTR ; See if a letter JP C,CHARTY ; Not a letter - Check type SVNAM2: LD C,A ; Save second byte of name ENDNAM: CALL GETCHR ; Get next character JP C,ENDNAM ; Numeric - Get another CALL CHKLTR ; See if a letter JP NC,ENDNAM ; Letter - Get another CHARTY: SUB '$' ; String variable? JP NZ,NOTSTR ; No - Numeric variable INC A ; A = 1 (string type) LD (TYPE),A ; Set type to string RRCA ; A = 80H , Flag for string ADD A,C ; 2nd byte of name has bit 7 on LD C,A ; Resave second byte on name CALL GETCHR ; Get next character NOTSTR: LD A,(FORFLG) ; Array name needed ? DEC A JP Z,ARLDSV ; Yes - Get array name JP P,NSCFOR ; No array with "FOR" or "FN" LD A,(HL) ; Get byte again SUB '(' ; Subscripted variable? JP Z,SBSCPT ; Yes - Sort out subscript ; NSCFOR: XOR A ; Simple variable LD (FORFLG),A ; Clear "FOR" flag PUSH HL ; Save code string address LD D,B ; DE = Variable name to find LD E,C LD HL,(FNRGNM) ; FN argument name CALL CPDEHL ; Is it the FN argument? LD DE,FNARG ; Point to argument value JP Z,POPHRT ; Yes - Return FN argument value LD HL,(VAREND) ; End of variables EX DE,HL ; Address of end of search LD HL,(PROGND) ; Start of variables address FNDVAR: CALL CPDEHL ; End of variable list table? JP Z,CFEVAL ; Yes - Called from EVAL? LD A,C ; Get second byte of name SUB (HL) ; Compare with name in list INC HL ; Move on to first byte JP NZ,FNTHR ; Different - Find another LD A,B ; Get first byte of name SUB (HL) ; Compare with name in list FNTHR: INC HL ; Move on to LSB of value JP Z,RETADR ; Found - Return address INC HL ; <- Skip INC HL ; <- over INC HL ; <- F.P. INC HL ; <- value JP FNDVAR ; Keep looking ; CFEVAL: POP HL ; Restore code string address EX (SP),HL ; Get return address PUSH DE ; Save address of variable LD DE,FRMEVL ; Return address in EVAL CALL CPDEHL ; Called from EVAL ? POP DE ; Restore address of variable JP Z,RETNUL ; Yes - Return null variable EX (SP),HL ; Put back return PUSH HL ; Save code string address PUSH BC ; Save variable name LD BC,6 ; 2 byte name plus 4 byte data LD HL,(ARREND) ; End of arrays PUSH HL ; Save end of arrays ADD HL,BC ; Move up 6 bytes POP BC ; Source address in BC PUSH HL ; Save new end address CALL MOVUP ; Move arrays up POP HL ; Restore new end address LD (ARREND),HL ; Set new end address LD H,B ; End of variables to HL LD L,C LD (VAREND),HL ; Set new end address ; ZEROLP: DEC HL ; Back through to zero variable LD (HL),0 ; Zero byte in variable CALL CPDEHL ; Done them all? JP NZ,ZEROLP ; No - Keep on going POP DE ; Get variable name LD (HL),E ; Store second character INC HL LD (HL),D ; Store first character INC HL RETADR: EX DE,HL ; Address of variable in DE POP HL ; Restore code string address RET ; RETNUL: LD (FPEXP),A ; Set result to zero LD HL,ZERBYT ; Also set a null string LD (FPREG),HL ; Save for EVAL POP HL ; Restore code string address RET ; SBSCPT: PUSH HL ; Save code string address LD HL,(LCRFLG) ; Locate/Create and Type EX (SP),HL ; Save and get code string LD D,A ; Zero number of dimensions SCPTLP: PUSH DE ; Save number of dimensions PUSH BC ; Save array name CALL FPSINT ; Get subscript (0-32767) POP BC ; Restore array name POP AF ; Get number of dimensions EX DE,HL EX (SP),HL ; Save subscript value PUSH HL ; Save LCRFLG and TYPE EX DE,HL INC A ; Count dimensions LD D,A ; Save in D LD A,(HL) ; Get next byte in code string CP ',' ; Comma (more to come)? JP Z,SCPTLP ; Yes - More subscripts CALL CHKSYN ; Make sure ")" follows DB ")" LD (NXTOPR),HL ; Save code string address POP HL ; Get LCRFLG and TYPE LD (LCRFLG),HL ; Restore Locate/create & type LD E,0 ; Flag not CSAVE* or CLOAD* PUSH DE ; Save number of dimensions (D) DB 11H ; Skip "PUSH HL" and "PUSH AF' ; ARLDSV: PUSH HL ; Save code string address PUSH AF ; A = 00 , Flags set = Z,N LD HL,(VAREND) ; Start of arrays DB 3EH ; Skip "ADD HL,DE" FNDARY: ADD HL,DE ; Move to next array start EX DE,HL LD HL,(ARREND) ; End of arrays EX DE,HL ; Current array pointer CALL CPDEHL ; End of arrays found? JP Z,CREARY ; Yes - Create array LD A,(HL) ; Get second byte of name CP C ; Compare with name given INC HL ; Move on JP NZ,NXTARY ; Different - Find next array LD A,(HL) ; Get first byte of name CP B ; Compare with name given NXTARY: INC HL ; Move on LD E,(HL) ; Get LSB of next array address INC HL LD D,(HL) ; Get MSB of next array address INC HL JP NZ,FNDARY ; Not found - Keep looking LD A,(LCRFLG) ; Found Locate or Create it? OR A JP NZ,DDERR ; Create - ?DD Error POP AF ; Locate - Get number of dim'ns LD B,H ; BC Points to array dim'ns LD C,L JP Z,POPHRT ; Jump if array load/save SUB (HL) ; Same number of dimensions? JP Z,FINDEL ; Yes - Find element BSERR: LD E,BS ; ?BS Error JP ERROR ; Output error ; CREARY: LD DE,4 ; 4 Bytes per entry POP AF ; Array to save or 0 dim'ns? JP Z,FCERR ; Yes - ?FC Error LD (HL),C ; Save second byte of name INC HL LD (HL),B ; Save first byte of name INC HL LD C,A ; Number of dimensions to C CALL CHKSTK ; Check if enough memory INC HL ; Point to number of dimensions INC HL LD (CUROPR),HL ; Save address of pointer LD (HL),C ; Set number of dimensions INC HL LD A,(LCRFLG) ; Locate of Create? RLA ; Carry set = Create LD A,C ; Get number of dimensions CRARLP: LD BC,10+1 ; Default dimension size 10 JP NC,DEFSIZ ; Locate - Set default size POP BC ; Get specified dimension size INC BC ; Include zero element DEFSIZ: LD (HL),C ; Save LSB of dimension size INC HL LD (HL),B ; Save MSB of dimension size INC HL PUSH AF ; Save num' of dim'ns an status PUSH HL ; Save address of dim'n size CALL MLDEBC ; Multiply DE by BC to find EX DE,HL ; amount of mem needed (to DE) POP HL ; Restore address of dimension POP AF ; Restore number of dimensions DEC A ; Count them JP NZ,CRARLP ; Do next dimension if more PUSH AF ; Save locate/create flag LD B,D ; MSB of memory needed LD C,E ; LSB of memory needed EX DE,HL ADD HL,DE ; Add bytes to array start JP C,OMERR ; Too big - Error CALL ENFMEM ; See if enough memory LD (ARREND),HL ; Save new end of array ; ZERARY: DEC HL ; Back through array data LD (HL),0 ; Set array element to zero CALL CPDEHL ; All elements zeroed? JP NZ,ZERARY ; No - Keep on going INC BC ; Number of bytes + 1 LD D,A ; A=0 LD HL,(CUROPR) ; Get address of array LD E,(HL) ; Number of dimensions EX DE,HL ; To HL ADD HL,HL ; Two bytes per dimension size ADD HL,BC ; Add number of bytes EX DE,HL ; Bytes needed to DE DEC HL DEC HL LD (HL),E ; Save LSB of bytes needed INC HL LD (HL),D ; Save MSB of bytes needed INC HL POP AF ; Locate / Create? JP C,ENDDIM ; A is 0 , End if create FINDEL: LD B,A ; Find array element LD C,A LD A,(HL) ; Number of dimensions INC HL DB 16H ; Skip "POP HL" FNDELP: POP HL ; Address of next dim' size LD E,(HL) ; Get LSB of dim'n size INC HL LD D,(HL) ; Get MSB of dim'n size INC HL EX (SP),HL ; Save address - Get index PUSH AF ; Save number of dim'ns CALL CPDEHL ; Dimension too large? JP NC,BSERR ; Yes - ?BS Error PUSH HL ; Save index CALL MLDEBC ; Multiply previous by size POP DE ; Index supplied to DE ADD HL,DE ; Add index to pointer POP AF ; Number of dimensions DEC A ; Count them LD B,H ; MSB of pointer LD C,L ; LSB of pointer JP NZ,FNDELP ; More - Keep going ADD HL,HL ; 4 Bytes per element ADD HL,HL POP BC ; Start of array ADD HL,BC ; Point to element EX DE,HL ; Address of element to DE ENDDIM: LD HL,(NXTOPR) ; Got code string address RET ; FRE: LD HL,(ARREND) ; Start of free memory EX DE,HL ; To DE LD HL,0 ; End of free memory ADD HL,SP ; Current stack value LD A,(TYPE) ; Dummy argument type OR A JP Z,FRENUM ; Numeric - Free variable space CALL GSTRCU ; Current string to pool CALL GARBGE ; Garbage collection LD HL,(STRSPC) ; Bottom of string space in use EX DE,HL ; To DE LD HL,(STRBOT) ; Bottom of string space FRENUM: LD A,L ; Get LSB of end SUB E ; Subtract LSB of beginning LD C,A ; Save difference if C LD A,H ; Get MSB of end SBC A,D ; Subtract MSB of beginning ACPASS: LD B,C ; Return integer AC ABPASS: LD D,B ; Return integer AB LD E,0 LD HL,TYPE ; Point to type LD (HL),E ; Set type to numeric LD B,80H+16 ; 16 bit integer JP RETINT ; Return the integr ; POS: LD A,(CURPOS) ; Get cursor position PASSA: LD B,A ; Put A into AB XOR A ; Zero A JP ABPASS ; Return integer AB ; DEF: CALL CHEKFN ; Get "FN" and name CALL IDTEST ; Test for illegal direct LD BC,DATA ; To get next statement PUSH BC ; Save address for RETurn PUSH DE ; Save address of function ptr CALL CHKSYN ; Make sure "(" follows DB "(" CALL GETVAR ; Get argument variable name PUSH HL ; Save code string address EX DE,HL ; Argument address to HL DEC HL LD D,(HL) ; Get first byte of arg name DEC HL LD E,(HL) ; Get second byte of arg name POP HL ; Restore code string address CALL TSTNUM ; Make sure numeric argument CALL CHKSYN ; Make sure ")" follows DB ")" CALL CHKSYN ; Make sure "=" follows DB ZEQUAL ; "=" token LD B,H ; Code string address to BC LD C,L EX (SP),HL ; Save code str , Get FN ptr LD (HL),C ; Save LSB of FN code string INC HL LD (HL),B ; Save MSB of FN code string JP SVSTAD ; Save address and do function ; DOFN: CALL CHEKFN ; Make sure FN follows PUSH DE ; Save function pointer address CALL EVLPAR ; Evaluate expression in "()" CALL TSTNUM ; Make sure numeric result EX (SP),HL ; Save code str , Get FN ptr LD E,(HL) ; Get LSB of FN code string INC HL LD D,(HL) ; Get MSB of FN code string INC HL LD A,D ; And function DEFined? OR E JP Z,UFERR ; No - ?UF Error LD A,(HL) ; Get LSB of argument address INC HL LD H,(HL) ; Get MSB of argument address LD L,A ; HL = Arg variable address PUSH HL ; Save it LD HL,(FNRGNM) ; Get old argument name EX (SP),HL; ; Save old , Get new LD (FNRGNM),HL ; Set new argument name LD HL,(FNARG+2) ; Get LSB,NLSB of old arg value PUSH HL ; Save it LD HL,(FNARG) ; Get MSB,EXP of old arg value PUSH HL ; Save it LD HL,FNARG ; HL = Value of argument PUSH DE ; Save FN code string address CALL FPTHL ; Move FPREG to argument POP HL ; Get FN code string address CALL GETNUM ; Get value from function DEC HL ; DEC 'cos GETCHR INCs CALL GETCHR ; Get next character JP NZ,SNERR ; Bad character in FN - Error POP HL ; Get MSB,EXP of old arg LD (FNARG),HL ; Restore it POP HL ; Get LSB,NLSB of old arg LD (FNARG+2),HL ; Restore it POP HL ; Get name of old arg LD (FNRGNM),HL ; Restore it POP HL ; Restore code string address RET ; IDTEST: PUSH HL ; Save code string address LD HL,(LINEAT) ; Get current line number INC HL ; -1 means direct statement LD A,H OR L POP HL ; Restore code string address RET NZ ; Return if in program LD E,ID ; ?ID Error JP ERROR ; CHEKFN: CALL CHKSYN ; Make sure FN follows DB ZFN ; "FN" token LD A,80H LD (FORFLG),A ; Flag FN name to find OR (HL) ; FN name has bit 7 set LD B,A ; in first byte of name CALL GTFNAM ; Get FN name JP TSTNUM ; Make sure numeric function ; STR: CALL TSTNUM ; Make sure it's a number CALL NUMASC ; Turn number into text STR1: CALL CRTST ; Create string entry for it CALL GSTRCU ; Current string to pool LD BC,TOPOOL ; Save in string pool PUSH BC ; Save address on stack ; SAVSTR: LD A,(HL) ; Get string length INC HL INC HL PUSH HL ; Save pointer to string CALL TESTR ; See if enough string space POP HL ; Restore pointer to string LD C,(HL) ; Get LSB of address INC HL LD B,(HL) ; Get MSB of address CALL CRTMST ; Create string entry PUSH HL ; Save pointer to MSB of addr LD L,A ; Length of string CALL TOSTRA ; Move to string area POP DE ; Restore pointer to MSB RET ; MKTMST: CALL TESTR ; See if enough string space CRTMST: LD HL,TMPSTR ; Temporary string PUSH HL ; Save it LD (HL),A ; Save length of string INC HL SVSTAD: INC HL LD (HL),E ; Save LSB of address INC HL LD (HL),D ; Save MSB of address POP HL ; Restore pointer RET ; CRTST: DEC HL ; DEC - INCed after QTSTR: LD B,'"' ; Terminating quote LD D,B ; Quote to D DTSTR: PUSH HL ; Save start LD C,-1 ; Set counter to -1 QTSTLP: INC HL ; Move on LD A,(HL) ; Get byte INC C ; Count bytes OR A ; End of line? JP Z,CRTSTE ; Yes - Create string entry CP D ; Terminator D found? JP Z,CRTSTE ; Yes - Create string entry CP B ; Terminator B found? JP NZ,QTSTLP ; No - Keep looking CRTSTE: CP '"' ; End with '"'? CALL Z,GETCHR ; Yes - Get next character EX (SP),HL ; Starting quote INC HL ; First byte of string EX DE,HL ; To DE LD A,C ; Get length CALL CRTMST ; Create string entry TSTOPL: LD DE,TMPSTR ; Temporary string LD HL,(TMSTPT) ; Temporary string pool pointer LD (FPREG),HL ; Save address of string ptr LD A,1 LD (TYPE),A ; Set type to string CALL DETHL4 ; Move string to pool CALL CPDEHL ; Out of string pool? LD (TMSTPT),HL ; Save new pointer POP HL ; Restore code string address LD A,(HL) ; Get next code byte RET NZ ; Return if pool OK LD E,ST ; ?ST Error JP ERROR ; String pool overflow ; PRNUMS: INC HL ; Skip leading space PRS: CALL CRTST ; Create string entry for it PRS1: CALL GSTRCU ; Current string to pool CALL LOADFP ; Move string block to BCDE INC E ; Length + 1 PRSLP: DEC E ; Count characters RET Z ; End of string LD A,(BC) ; Get byte to output CALL OUTC ; Output character in A CP CR ; Return? CALL Z,DONULL ; Yes - Do nulls INC BC ; Next byte in string JP PRSLP ; More characters to output ; TESTR: OR A ; Test if enough room DB 0EH ; No garbage collection done GRBDON: POP AF ; Garbage collection done PUSH AF ; Save status LD HL,(STRSPC) ; Bottom of string space in use EX DE,HL ; To DE LD HL,(STRBOT) ; Bottom of string area CPL ; Negate length (Top down) LD C,A ; -Length to BC LD B,-1 ; BC = -ve length of string ADD HL,BC ; Add to bottom of space in use INC HL ; Plus one for 2's complement CALL CPDEHL ; Below string RAM area? JP C,TESTOS ; Tidy up if not done else err LD (STRBOT),HL ; Save new bottom of area INC HL ; Point to first byte of string EX DE,HL ; Address to DE POPAF: POP AF ; Throw away status push RET ; TESTOS: POP AF ; Garbage collect been done? LD E,OS ; ?OS Error JP Z,ERROR ; Yes - Not enough string apace CP A ; Flag garbage collect done PUSH AF ; Save status LD BC,GRBDON ; Garbage collection done PUSH BC ; Save for RETurn GARBGE: LD HL,(LSTRAM) ; Get end of RAM pointer GARBLP: LD (STRBOT),HL ; Reset string pointer LD HL,0 PUSH HL ; Flag no string found LD HL,(STRSPC) ; Get bottom of string space PUSH HL ; Save bottom of string space LD HL,TMSTPL ; Temporary string pool GRBLP: EX DE,HL LD HL,(TMSTPT) ; Temporary string pool pointer EX DE,HL CALL CPDEHL ; Temporary string pool done? LD BC,GRBLP ; Loop until string pool done JP NZ,STPOOL ; No - See if in string area LD HL,(PROGND) ; Start of simple variables SMPVAR: EX DE,HL LD HL,(VAREND) ; End of simple variables EX DE,HL CALL CPDEHL ; All simple strings done? JP Z,ARRLP ; Yes - Do string arrays LD A,(HL) ; Get type of variable INC HL INC HL OR A ; "S" flag set if string CALL STRADD ; See if string in string area JP SMPVAR ; Loop until simple ones done ; GNXARY: POP BC ; Scrap address of this array ARRLP: EX DE,HL LD HL,(ARREND) ; End of string arrays EX DE,HL CALL CPDEHL ; All string arrays done? JP Z,SCNEND ; Yes - Move string if found CALL LOADFP ; Get array name to BCDE LD A,E ; Get type of array PUSH HL ; Save address of num of dim'ns ADD HL,BC ; Start of next array OR A ; Test type of array JP P,GNXARY ; Numeric array - Ignore it LD (CUROPR),HL ; Save address of next array POP HL ; Get address of num of dim'ns LD C,(HL) ; BC = Number of dimensions LD B,0 ADD HL,BC ; Two bytes per dimension size ADD HL,BC INC HL ; Plus one for number of dim'ns GRBARY: EX DE,HL LD HL,(CUROPR) ; Get address of next array EX DE,HL CALL CPDEHL ; Is this array finished? JP Z,ARRLP ; Yes - Get next one LD BC,GRBARY ; Loop until array all done STPOOL: PUSH BC ; Save return address OR 80H ; Flag string type STRADD: LD A,(HL) ; Get string length INC HL INC HL LD E,(HL) ; Get LSB of string address INC HL LD D,(HL) ; Get MSB of string address INC HL RET P ; Not a string - Return OR A ; Set flags on string length RET Z ; Null string - Return LD B,H ; Save variable pointer LD C,L LD HL,(STRBOT) ; Bottom of new area CALL CPDEHL ; String been done? LD H,B ; Restore variable pointer LD L,C RET C ; String done - Ignore POP HL ; Return address EX (SP),HL ; Lowest available string area CALL CPDEHL ; String within string area? EX (SP),HL ; Lowest available string area PUSH HL ; Re-save return address LD H,B ; Restore variable pointer LD L,C RET NC ; Outside string area - Ignore POP BC ; Get return , Throw 2 away POP AF ; POP AF ; PUSH HL ; Save variable pointer PUSH DE ; Save address of current PUSH BC ; Put back return address RET ; Go to it ; SCNEND: POP DE ; Addresses of strings POP HL ; LD A,L ; HL = 0 if no more to do OR H RET Z ; No more to do - Return DEC HL LD B,(HL) ; MSB of address of string DEC HL LD C,(HL) ; LSB of address of string PUSH HL ; Save variable address DEC HL DEC HL LD L,(HL) ; HL = Length of string LD H,0 ADD HL,BC ; Address of end of string+1 LD D,B ; String address to DE LD E,C DEC HL ; Last byte in string LD B,H ; Address to BC LD C,L LD HL,(STRBOT) ; Current bottom of string area CALL MOVSTR ; Move string to new address POP HL ; Restore variable address LD (HL),C ; Save new LSB of address INC HL LD (HL),B ; Save new MSB of address LD L,C ; Next string area+1 to HL LD H,B DEC HL ; Next string area address JP GARBLP ; Look for more strings ; CONCAT: PUSH BC ; Save prec' opr & code string PUSH HL ; LD HL,(FPREG) ; Get first string EX (SP),HL ; Save first string CALL OPRND ; Get second string EX (SP),HL ; Restore first string CALL TSTSTR ; Make sure it's a string LD A,(HL) ; Get length of second string PUSH HL ; Save first string LD HL,(FPREG) ; Get second string PUSH HL ; Save second string ADD A,(HL) ; Add length of second string LD E,LS ; ?LS Error JP C,ERROR ; String too long - Error CALL MKTMST ; Make temporary string POP DE ; Get second string to DE CALL GSTRDE ; Move to string pool if needed EX (SP),HL ; Get first string CALL GSTRHL ; Move to string pool if needed PUSH HL ; Save first string LD HL,(TMPSTR+2) ; Temporary string address EX DE,HL ; To DE CALL SSTSA ; First string to string area CALL SSTSA ; Second string to string area LD HL,EVAL2 ; Return to evaluation loop EX (SP),HL ; Save return,get code string PUSH HL ; Save code string address JP TSTOPL ; To temporary string to pool ; SSTSA: POP HL ; Return address EX (SP),HL ; Get string block,save return LD A,(HL) ; Get length of string INC HL INC HL LD C,(HL) ; Get LSB of string address INC HL LD B,(HL) ; Get MSB of string address LD L,A ; Length to L TOSTRA: INC L ; INC - DECed after TSALP: DEC L ; Count bytes moved RET Z ; End of string - Return LD A,(BC) ; Get source LD (DE),A ; Save destination INC BC ; Next source INC DE ; Next destination JP TSALP ; Loop until string moved ; GETSTR: CALL TSTSTR ; Make sure it's a string GSTRCU: LD HL,(FPREG) ; Get current string GSTRHL: EX DE,HL ; Save DE GSTRDE: CALL BAKTMP ; Was it last tmp-str? EX DE,HL ; Restore DE RET NZ ; No - Return PUSH DE ; Save string LD D,B ; String block address to DE LD E,C DEC DE ; Point to length LD C,(HL) ; Get string length LD HL,(STRBOT) ; Current bottom of string area CALL CPDEHL ; Last one in string area? JP NZ,POPHL ; No - Return LD B,A ; Clear B (A=0) ADD HL,BC ; Remove string from str' area LD (STRBOT),HL ; Save new bottom of str' area POPHL: POP HL ; Restore string RET ; BAKTMP: LD HL,(TMSTPT) ; Get temporary string pool top DEC HL ; Back LD B,(HL) ; Get MSB of address DEC HL ; Back LD C,(HL) ; Get LSB of address DEC HL ; Back DEC HL ; Back CALL CPDEHL ; String last in string pool? RET NZ ; Yes - Leave it LD (TMSTPT),HL ; Save new string pool top RET ; LEN: LD BC,PASSA ; To return integer A PUSH BC ; Save address GETLEN: CALL GETSTR ; Get string and its length XOR A LD D,A ; Clear D LD (TYPE),A ; Set type to numeric LD A,(HL) ; Get length of string OR A ; Set status flags RET ; ASC: LD BC,PASSA ; To return integer A PUSH BC ; Save address GTFLNM: CALL GETLEN ; Get length of string JP Z,FCERR ; Null string - Error INC HL INC HL LD E,(HL) ; Get LSB of address INC HL LD D,(HL) ; Get MSB of address LD A,(DE) ; Get first byte of string RET ; CHR: LD A,1 ; One character string CALL MKTMST ; Make a temporary string CALL MAKINT ; Make it integer A LD HL,(TMPSTR+2) ; Get address of string LD (HL),E ; Save character TOPOOL: POP BC ; Clean up stack JP TSTOPL ; Temporary string to pool ; LEFT: CALL LFRGNM ; Get number and ending ")" XOR A ; Start at first byte in string RIGHT1: EX (SP),HL ; Save code string,Get string LD C,A ; Starting position in string MID1: PUSH HL ; Save string block address LD A,(HL) ; Get length of string CP B ; Compare with number given JP C,ALLFOL ; All following bytes required LD A,B ; Get new length DB 11H ; Skip "LD C,0" ALLFOL: LD C,0 ; First byte of string PUSH BC ; Save position in string CALL TESTR ; See if enough string space POP BC ; Get position in string POP HL ; Restore string block address PUSH HL ; And re-save it INC HL INC HL LD B,(HL) ; Get LSB of address INC HL LD H,(HL) ; Get MSB of address LD L,B ; HL = address of string LD B,0 ; BC = starting address ADD HL,BC ; Point to that byte LD B,H ; BC = source string LD C,L CALL CRTMST ; Create a string entry LD L,A ; Length of new string CALL TOSTRA ; Move string to string area POP DE ; Clear stack CALL GSTRDE ; Move to string pool if needed JP TSTOPL ; Temporary string to pool ; RIGHT: CALL LFRGNM ; Get number and ending ")" POP DE ; Get string length PUSH DE ; And re-save LD A,(DE) ; Get length SUB B ; Move back N bytes JP RIGHT1 ; Go and get sub-string ; MID: EX DE,HL ; Get code string address LD A,(HL) ; Get next byte ',' or ")" CALL MIDNUM ; Get number supplied INC B ; Is it character zero? DEC B JP Z,FCERR ; Yes - Error PUSH BC ; Save starting position LD E,255 ; All of string CP ')' ; Any length given? JP Z,RSTSTR ; No - Rest of string CALL CHKSYN ; Make sure ',' follows DB ',' CALL GETINT ; Get integer 0-255 RSTSTR: CALL CHKSYN ; Make sure ")" follows DB ")" POP AF ; Restore starting position EX (SP),HL ; Get string,8ave code string LD BC,MID1 ; Continuation of MID$ routine PUSH BC ; Save for return DEC A ; Starting position-1 CP (HL) ; Compare with length LD B,0 ; Zero bytes length RET NC ; Null string if start past end LD C,A ; Save starting position-1 LD A,(HL) ; Get length of string SUB C ; Subtract start CP E ; Enough string for it? LD B,A ; Save maximum length available RET C ; Truncate string if needed LD B,E ; Set specified length RET ; Go and create string ; VAL: CALL GETLEN ; Get length of string JP Z,RESZER ; Result zero LD E,A ; Save length INC HL INC HL LD A,(HL) ; Get LSB of address INC HL LD H,(HL) ; Get MSB of address LD L,A ; HL = String address PUSH HL ; Save string address ADD HL,DE LD B,(HL) ; Get end of string+1 byte LD (HL),D ; Zero it to terminate EX (SP),HL ; Save string end,get start PUSH BC ; Save end+1 byte LD A,(HL) ; Get starting byte CP '$' ; Hex number indicated? [function added] JP NZ,VAL1 CALL HEXTFP ; Convert Hex to FPREG JR VAL3 VAL1: CP '%' ; Binary number indicated? [function added] JP NZ,VAL2 CALL BINTFP ; Convert Bin to FPREG JR VAL3 VAL2: CALL ASCTFP ; Convert ASCII string to FP VAL3: POP BC ; Restore end+1 byte POP HL ; Restore end+1 address LD (HL),B ; Put back original byte RET ; LFRGNM: EX DE,HL ; Code string address to HL CALL CHKSYN ; Make sure ")" follows DB ")" MIDNUM: POP BC ; Get return address POP DE ; Get number supplied PUSH BC ; Re-save return address LD B,E ; Number to B RET ; INP: CALL MAKINT ; Make it integer A LD (INPORT),A ; Set input port CALL INPSUB ; Get input from port JP PASSA ; Return integer A ; POUT: CALL SETIO ; Set up port number JP OUTSUB ; Output data and return ; WAIT: CALL SETIO ; Set up port number PUSH AF ; Save AND mask LD E,0 ; Assume zero if none given DEC HL ; DEC 'cos GETCHR INCs CALL GETCHR ; Get next character JP Z,NOXOR ; No XOR byte given CALL CHKSYN ; Make sure ',' follows DB ',' CALL GETINT ; Get integer 0-255 to XOR with NOXOR: POP BC ; Restore AND mask WAITLP: CALL INPSUB ; Get input XOR E ; Flip selected bits AND B ; Result non-zero? JP Z,WAITLP ; No = keep waiting RET ; SETIO: CALL GETINT ; Get integer 0-255 LD (INPORT),A ; Set input port LD (OTPORT),A ; Set output port CALL CHKSYN ; Make sure ',' follows DB ',' JP GETINT ; Get integer 0-255 and return ; FNDNUM: CALL GETCHR ; Get next character GETINT: CALL GETNUM ; Get a number from 0 to 255 MAKINT: CALL DEPINT ; Make sure value 0 - 255 LD A,D ; Get MSB of number OR A ; Zero? JP NZ,FCERR ; No - Error DEC HL ; DEC 'cos GETCHR INCs CALL GETCHR ; Get next character LD A,E ; Get number to A RET ; PEEK: CALL DEINT ; Get memory address LD A,(DE) ; Get byte in memory JP PASSA ; Return integer A ; POKE: CALL GETNUM ; Get memory address CALL DEINT ; Get integer -32768 to 3276 PUSH DE ; Save memory address CALL CHKSYN ; Make sure ',' follows DB ',' CALL GETINT ; Get integer 0-255 POP DE ; Restore memory address LD (DE),A ; Load it into memory RET ; ROUND: LD HL,HALF ; Add 0.5 to FPREG ADDPHL: CALL LOADFP ; Load FP at (HL) to BCDE JP FPADD ; Add BCDE to FPREG ; SUBPHL: CALL LOADFP ; FPREG = -FPREG + number at HL DB 21H ; Skip "POP BC" and "POP DE" PSUB: POP BC ; Get FP number from stack POP DE SUBCDE: CALL INVSGN ; Negate FPREG FPADD: LD A,B ; Get FP exponent OR A ; Is number zero? RET Z ; Yes - Nothing to add LD A,(FPEXP) ; Get FPREG exponent OR A ; Is this number zero? JP Z,FPBCDE ; Yes - Move BCDE to FPREG SUB B ; BCDE number larger? JP NC,NOSWAP ; No - Don't swap them CPL ; Two's complement INC A ; FP exponent EX DE,HL CALL STAKFP ; Put FPREG on stack EX DE,HL CALL FPBCDE ; Move BCDE to FPREG POP BC ; Restore number from stack POP DE NOSWAP: CP 24+1 ; Second number insignificant? RET NC ; Yes - First number is result PUSH AF ; Save number of bits to scale CALL SIGNS ; Set MSBs & sign of result LD H,A ; Save sign of result POP AF ; Restore scaling factor CALL SCALE ; Scale BCDE to same exponent OR H ; Result to be positive? LD HL,FPREG ; Point to FPREG JP P,MINCDE ; No - Subtract FPREG from CDE CALL PLUCDE ; Add FPREG to CDE JP NC,RONDUP ; No overflow - Round it up INC HL ; Point to exponent INC (HL) ; Increment it JP Z,OVERR ; Number overflowed - Error LD L,1 ; 1 bit to shift right CALL SHRT1 ; Shift result right JP RONDUP ; Round it up ; MINCDE: XOR A ; Clear A and carry SUB B ; Negate exponent LD B,A ; Re-save exponent LD A,(HL) ; Get LSB of FPREG SBC A, E ; Subtract LSB of BCDE LD E,A ; Save LSB of BCDE INC HL LD A,(HL) ; Get NMSB of FPREG SBC A,D ; Subtract NMSB of BCDE LD D,A ; Save NMSB of BCDE INC HL LD A,(HL) ; Get MSB of FPREG SBC A,C ; Subtract MSB of BCDE LD C,A ; Save MSB of BCDE CONPOS: CALL C,COMPL ; Overflow - Make it positive ; BNORM: LD L,B ; L = Exponent LD H,E ; H = LSB XOR A BNRMLP: LD B,A ; Save bit count LD A,C ; Get MSB OR A ; Is it zero? JP NZ,PNORM ; No - Do it bit at a time LD C,D ; MSB = NMSB LD D,H ; NMSB= LSB LD H,L ; LSB = VLSB LD L,A ; VLSB= 0 LD A,B ; Get exponent SUB 8 ; Count 8 bits CP 0E0H ; -24-8 Was number zero? JP NZ,BNRMLP ; No - Keep normalising RESZER: XOR A ; Result is zero SAVEXP: LD (FPEXP),A ; Save result as zero RET ; NORMAL: DEC B ; Count bits ADD HL,HL ; Shift HL left LD A,D ; Get NMSB RLA ; Shift left with last bit LD D,A ; Save NMSB LD A,C ; Get MSB ADC A,A ; Shift left with last bit LD C,A ; Save MSB PNORM: JP P,NORMAL ; Not done - Keep going LD A,B ; Number of bits shifted LD E,H ; Save HL in EB LD B,L OR A ; Any shifting done? JP Z,RONDUP ; No - Round it up LD HL,FPEXP ; Point to exponent ADD A,(HL) ; Add shifted bits LD (HL),A ; Re-save exponent JP NC,RESZER ; Underflow - Result is zero RET Z ; Result is zero RONDUP: LD A,B ; Get VLSB of number RONDB: LD HL,FPEXP ; Point to exponent OR A ; Any rounding? CALL M,FPROND ; Yes - Round number up LD B,(HL) ; B = Exponent INC HL LD A,(HL) ; Get sign of result AND 10000000B ; Only bit 7 needed XOR C ; Set correct sign LD C,A ; Save correct sign in number JP FPBCDE ; Move BCDE to FPREG ; FPROND: INC E ; Round LSB RET NZ ; Return if ok INC D ; Round NMSB RET NZ ; Return if ok INC C ; Round MSB RET NZ ; Return if ok LD C,80H ; Set normal value INC (HL) ; Increment exponent RET NZ ; Return if ok JP OVERR ; Overflow error ; PLUCDE: LD A,(HL) ; Get LSB of FPREG ADD A,E ; Add LSB of BCDE LD E,A ; Save LSB of BCDE INC HL LD A,(HL) ; Get NMSB of FPREG ADC A,D ; Add NMSB of BCDE LD D,A ; Save NMSB of BCDE INC HL LD A,(HL) ; Get MSB of FPREG ADC A,C ; Add MSB of BCDE LD C,A ; Save MSB of BCDE RET ; COMPL: LD HL,SGNRES ; Sign of result LD A,(HL) ; Get sign of result CPL ; Negate it LD (HL),A ; Put it back XOR A LD L,A ; Set L to zero SUB B ; Negate exponent,set carry LD B,A ; Re-save exponent LD A,L ; Load zero SBC A,E ; Negate LSB LD E,A ; Re-save LSB LD A,L ; Load zero SBC A,D ; Negate NMSB LD D,A ; Re-save NMSB LD A,L ; Load zero SBC A,C ; Negate MSB LD C,A ; Re-save MSB RET ; SCALE: LD B,0 ; Clear underflow SCALLP: SUB 8 ; 8 bits (a whole byte)? JP C,SHRITE ; No - Shift right A bits LD B,E ; <- Shift LD E,D ; <- right LD D,C ; <- eight LD C,0 ; <- bits JP SCALLP ; More bits to shift ; SHRITE: ADD A,8+1 ; Adjust count LD L,A ; Save bits to shift SHRLP: XOR A ; Flag for all done DEC L ; All shifting done? RET Z ; Yes - Return LD A,C ; Get MSB SHRT1: RRA ; Shift it right LD C,A ; Re-save LD A,D ; Get NMSB RRA ; Shift right with last bit LD D,A ; Re-save it LD A,E ; Get LSB RRA ; Shift right with last bit LD E,A ; Re-save it LD A,B ; Get underflow RRA ; Shift right with last bit LD B,A ; Re-save underflow JP SHRLP ; More bits to do ; UNITY: DB 000H,000H,000H,081H ; 1.00000 ; LOGTAB: DB 3 ; Table used by LOG DB 0AAH,056H,019H,080H ; 0.59898 DB 0F1H,022H,076H,080H ; 0.96147 DB 045H,0AAH,038H,082H ; 2.88539 ; LOG: CALL TSTSGN ; Test sign of value OR A JP PE,FCERR ; ?FC Error if <= zero LD HL,FPEXP ; Point to exponent LD A,(HL) ; Get exponent LD BC,8035H ; BCDE = SQR(1/2) LD DE,04F3H SUB B ; Scale value to be < 1 PUSH AF ; Save scale factor LD (HL),B ; Save new exponent PUSH DE ; Save SQR(1/2) PUSH BC CALL FPADD ; Add SQR(1/2) to value POP BC ; Restore SQR(1/2) POP DE INC B ; Make it SQR(2) CALL DVBCDE ; Divide by SQR(2) LD HL,UNITY ; Point to 1. CALL SUBPHL ; Subtract FPREG from 1 LD HL,LOGTAB ; Coefficient table CALL SUMSER ; Evaluate sum of series LD BC,8080H ; BCDE = -0.5 LD DE,0000H CALL FPADD ; Subtract 0.5 from FPREG POP AF ; Restore scale factor CALL RSCALE ; Re-scale number MULLN2: LD BC,8031H ; BCDE = Ln(2) LD DE,7218H DB 21H ; Skip "POP BC" and "POP DE" ; MULT: POP BC ; Get number from stack POP DE FPMULT: CALL TSTSGN ; Test sign of FPREG RET Z ; Return zero if zero LD L,0 ; Flag add exponents CALL ADDEXP ; Add exponents LD A,C ; Get MSB of multiplier LD (MULVAL),A ; Save MSB of multiplier EX DE,HL LD (MULVAL+1),HL ; Save rest of multiplier LD BC,0 ; Partial product (BCDE) = zero LD D,B LD E,B LD HL,BNORM ; Address of normalise PUSH HL ; Save for return LD HL,MULT8 ; Address of 8 bit multiply PUSH HL ; Save for NMSB,MSB PUSH HL ; LD HL,FPREG ; Point to number MULT8: LD A,(HL) ; Get LSB of number INC HL ; Point to NMSB OR A ; Test LSB JP Z,BYTSFT ; Zero - shift to next byte PUSH HL ; Save address of number LD L,8 ; 8 bits to multiply by MUL8LP: RRA ; Shift LSB right LD H,A ; Save LSB LD A,C ; Get MSB JP NC,NOMADD ; Bit was zero - Don't add PUSH HL ; Save LSB and count LD HL,(MULVAL+1) ; Get LSB and NMSB ADD HL,DE ; Add NMSB and LSB EX DE,HL ; Leave sum in DE POP HL ; Restore MSB and count LD A,(MULVAL) ; Get MSB of multiplier ADC A,C ; Add MSB NOMADD: RRA ; Shift MSB right LD C,A ; Re-save MSB LD A,D ; Get NMSB RRA ; Shift NMSB right LD D,A ; Re-save NMSB LD A,E ; Get LSB RRA ; Shift LSB right LD E,A ; Re-save LSB LD A,B ; Get VLSB RRA ; Shift VLSB right LD B,A ; Re-save VLSB DEC L ; Count bits multiplied LD A,H ; Get LSB of multiplier JP NZ,MUL8LP ; More - Do it POPHRT: POP HL ; Restore address of number RET ; BYTSFT: LD B,E ; Shift partial product left LD E,D LD D,C LD C,A RET ; DIV10: CALL STAKFP ; Save FPREG on stack LD BC,8420H ; BCDE = 10. LD DE,0000H CALL FPBCDE ; Move 10 to FPREG ; DIV: POP BC ; Get number from stack POP DE DVBCDE: CALL TSTSGN ; Test sign of FPREG JP Z,DZERR ; Error if division by zero LD L,-1 ; Flag subtract exponents CALL ADDEXP ; Subtract exponents INC (HL) ; Add 2 to exponent to adjust INC (HL) DEC HL ; Point to MSB LD A,(HL) ; Get MSB of dividend LD (DIV3),A ; Save for subtraction DEC HL LD A,(HL) ; Get NMSB of dividend LD (DIV2),A ; Save for subtraction DEC HL LD A,(HL) ; Get MSB of dividend LD (DIV1),A ; Save for subtraction LD B,C ; Get MSB EX DE,HL ; NMSB,LSB to HL XOR A LD C,A ; Clear MSB of quotient LD D,A ; Clear NMSB of quotient LD E,A ; Clear LSB of quotient LD (DIV4),A ; Clear overflow count DIVLP: PUSH HL ; Save divisor PUSH BC LD A,L ; Get LSB of number CALL DIVSUP ; Subt' divisor from dividend SBC A,0 ; Count for overflows CCF JP NC,RESDIV ; Restore divisor if borrow LD (DIV4),A ; Re-save overflow count POP AF ; Scrap divisor POP AF SCF ; Set carry to DB 0D2H ; Skip "POP BC" and "POP HL" ; RESDIV: POP BC ; Restore divisor POP HL LD A,C ; Get MSB of quotient INC A DEC A RRA ; Bit 0 to bit 7 JP M,RONDB ; Done - Normalise result RLA ; Restore carry LD A,E ; Get LSB of quotient RLA ; Double it LD E,A ; Put it back LD A,D ; Get NMSB of quotient RLA ; Double it LD D,A ; Put it back LD A,C ; Get MSB of quotient RLA ; Double it LD C,A ; Put it back ADD HL,HL ; Double NMSB,LSB of divisor LD A,B ; Get MSB of divisor RLA ; Double it LD B,A ; Put it back LD A,(DIV4) ; Get VLSB of quotient RLA ; Double it LD (DIV4),A ; Put it back LD A,C ; Get MSB of quotient OR D ; Merge NMSB OR E ; Merge LSB JP NZ,DIVLP ; Not done - Keep dividing PUSH HL ; Save divisor LD HL,FPEXP ; Point to exponent DEC (HL) ; Divide by 2 POP HL ; Restore divisor JP NZ,DIVLP ; Ok - Keep going JP OVERR ; Overflow error ; ADDEXP: LD A,B ; Get exponent of dividend OR A ; Test it JP Z,OVTST3 ; Zero - Result zero LD A,L ; Get add/subtract flag LD HL,FPEXP ; Point to exponent XOR (HL) ; Add or subtract it ADD A,B ; Add the other exponent LD B,A ; Save new exponent RRA ; Test exponent for overflow XOR B LD A,B ; Get exponent JP P,OVTST2 ; Positive - Test for overflow ADD A,80H ; Add excess 128 LD (HL),A ; Save new exponent JP Z,POPHRT ; Zero - Result zero CALL SIGNS ; Set MSBs and sign of result LD (HL),A ; Save new exponent DEC HL ; Point to MSB RET ; OVTST1: CALL TSTSGN ; Test sign of FPREG CPL ; Invert sign POP HL ; Clean up stack OVTST2: OR A ; Test if new exponent zero OVTST3: POP HL ; Clear off return address JP P,RESZER ; Result zero JP OVERR ; Overflow error ; MLSP10: CALL BCDEFP ; Move FPREG to BCDE LD A,B ; Get exponent OR A ; Is it zero? RET Z ; Yes - Result is zero ADD A,2 ; Multiply by 4 JP C,OVERR ; Overflow - ?OV Error LD B,A ; Re-save exponent CALL FPADD ; Add BCDE to FPREG (Times 5) LD HL,FPEXP ; Point to exponent INC (HL) ; Double number (Times 10) RET NZ ; Ok - Return JP OVERR ; Overflow error ; TSTSGN: LD A,(FPEXP) ; Get sign of FPREG OR A RET Z ; RETurn if number is zero LD A,(FPREG+2) ; Get MSB of FPREG DB 0FEH ; Test sign RETREL: CPL ; Invert sign RLA ; Sign bit to carry FLGDIF: SBC A,A ; Carry to all bits of A RET NZ ; Return -1 if negative INC A ; Bump to +1 RET ; Positive - Return +1 ; SGN: CALL TSTSGN ; Test sign of FPREG FLGREL: LD B,80H+8 ; 8 bit integer in exponent LD DE,0 ; Zero NMSB and LSB RETINT: LD HL,FPEXP ; Point to exponent LD C,A ; CDE = MSB,NMSB and LSB LD (HL),B ; Save exponent LD B,0 ; CDE = integer to normalise INC HL ; Point to sign of result LD (HL),80H ; Set sign of result RLA ; Carry = sign of integer JP CONPOS ; Set sign of result ; ABS: CALL TSTSGN ; Test sign of FPREG RET P ; Return if positive INVSGN: LD HL,FPREG+2 ; Point to MSB LD A,(HL) ; Get sign of mantissa XOR 80H ; Invert sign of mantissa LD (HL),A ; Re-save sign of mantissa RET ; STAKFP: EX DE,HL ; Save code string address LD HL,(FPREG) ; LSB,NLSB of FPREG EX (SP),HL ; Stack them,get return PUSH HL ; Re-save return LD HL,(FPREG+2) ; MSB and exponent of FPREG EX (SP),HL ; Stack them,get return PUSH HL ; Re-save return EX DE,HL ; Restore code string address RET ; PHLTFP: CALL LOADFP ; Number at HL to BCDE FPBCDE: EX DE,HL ; Save code string address LD (FPREG),HL ; Save LSB,NLSB of number LD H,B ; Exponent of number LD L,C ; MSB of number LD (FPREG+2),HL ; Save MSB and exponent EX DE,HL ; Restore code string address RET ; BCDEFP: LD HL,FPREG ; Point to FPREG LOADFP: LD E,(HL) ; Get LSB of number INC HL LD D,(HL) ; Get NMSB of number INC HL LD C,(HL) ; Get MSB of number INC HL LD B,(HL) ; Get exponent of number INCHL: INC HL ; Used for conditional "INC HL" RET ; FPTHL: LD DE,FPREG ; Point to FPREG DETHL4: LD B,4 ; 4 bytes to move DETHLB: LD A,(DE) ; Get source LD (HL),A ; Save destination INC DE ; Next source INC HL ; Next destination DEC B ; Count bytes JP NZ,DETHLB ; Loop if more RET ; SIGNS: LD HL,FPREG+2 ; Point to MSB of FPREG LD A,(HL) ; Get MSB RLCA ; Old sign to carry SCF ; Set MSBit RRA ; Set MSBit of MSB LD (HL),A ; Save new MSB CCF ; Complement sign RRA ; Old sign to carry INC HL INC HL LD (HL),A ; Set sign of result LD A,C ; Get MSB RLCA ; Old sign to carry SCF ; Set MSBit RRA ; Set MSBit of MSB LD C,A ; Save MSB RRA XOR (HL) ; New sign of result RET ; CMPNUM: LD A,B ; Get exponent of number OR A JP Z,TSTSGN ; Zero - Test sign of FPREG LD HL,RETREL ; Return relation routine PUSH HL ; Save for return CALL TSTSGN ; Test sign of FPREG LD A,C ; Get MSB of number RET Z ; FPREG zero - Number's MSB LD HL,FPREG+2 ; MSB of FPREG XOR (HL) ; Combine signs LD A,C ; Get MSB of number RET M ; Exit if signs different CALL CMPFP ; Compare FP numbers RRA ; Get carry to sign XOR C ; Combine with MSB of number RET ; CMPFP: INC HL ; Point to exponent LD A,B ; Get exponent CP (HL) ; Compare exponents RET NZ ; Different DEC HL ; Point to MBS LD A,C ; Get MSB CP (HL) ; Compare MSBs RET NZ ; Different DEC HL ; Point to NMSB LD A,D ; Get NMSB CP (HL) ; Compare NMSBs RET NZ ; Different DEC HL ; Point to LSB LD A,E ; Get LSB SUB (HL) ; Compare LSBs RET NZ ; Different POP HL ; Drop RETurn POP HL ; Drop another RETurn RET ; FPINT: LD B,A ; <- Move LD C,A ; <- exponent LD D,A ; <- to all LD E,A ; <- bits OR A ; Test exponent RET Z ; Zero - Return zero PUSH HL ; Save pointer to number CALL BCDEFP ; Move FPREG to BCDE CALL SIGNS ; Set MSBs & sign of result XOR (HL) ; Combine with sign of FPREG LD H,A ; Save combined signs CALL M,DCBCDE ; Negative - Decrement BCDE LD A,80H+24 ; 24 bits SUB B ; Bits to shift CALL SCALE ; Shift BCDE LD A,H ; Get combined sign RLA ; Sign to carry CALL C,FPROND ; Negative - Round number up LD B,0 ; Zero exponent CALL C,COMPL ; If negative make positive POP HL ; Restore pointer to number RET ; DCBCDE: DEC DE ; Decrement BCDE LD A,D ; Test LSBs AND E INC A RET NZ ; Exit if LSBs not FFFF DEC BC ; Decrement MSBs RET ; INT: LD HL,FPEXP ; Point to exponent LD A,(HL) ; Get exponent CP 80H+24 ; Integer accuracy only? LD A,(FPREG) ; Get LSB RET NC ; Yes - Already integer LD A,(HL) ; Get exponent CALL FPINT ; F.P to integer LD (HL),80H+24 ; Save 24 bit integer LD A,E ; Get LSB of number PUSH AF ; Save LSB LD A,C ; Get MSB of number RLA ; Sign to carry CALL CONPOS ; Set sign of result POP AF ; Restore LSB of number RET ; MLDEBC: LD HL,0 ; Clear partial product LD A,B ; Test multiplier OR C RET Z ; Return zero if zero LD A,16 ; 16 bits MLDBLP: ADD HL,HL ; Shift P.P left JP C,BSERR ; ?BS Error if overflow EX DE,HL ADD HL,HL ; Shift multiplier left EX DE,HL JP NC,NOMLAD ; Bit was zero - No add ADD HL,BC ; Add multiplicand JP C,BSERR ; ?BS Error if overflow NOMLAD: DEC A ; Count bits JP NZ,MLDBLP ; More RET ; ASCTFP: CP '-' ; Negative? PUSH AF ; Save it and flags JP Z,CNVNUM ; Yes - Convert number CP '+' ; Positive? JP Z,CNVNUM ; Yes - Convert number DEC HL ; DEC 'cos GETCHR INCs CNVNUM: CALL RESZER ; Set result to zero LD B,A ; Digits after point counter LD D,A ; Sign of exponent LD E,A ; Exponent of ten CPL LD C,A ; Before or after point flag MANLP: CALL GETCHR ; Get next character JP C,ADDIG ; Digit - Add to number CP '.' JP Z,DPOINT ; '.' - Flag point CP 'E' JP NZ,CONEXP ; Not 'E' - Scale number CALL GETCHR ; Get next character CALL SGNEXP ; Get sign of exponent EXPLP: CALL GETCHR ; Get next character JP C,EDIGIT ; Digit - Add to exponent INC D ; Is sign negative? JP NZ,CONEXP ; No - Scale number XOR A SUB E ; Negate exponent LD E,A ; And re-save it INC C ; Flag end of number DPOINT: INC C ; Flag point passed JP Z,MANLP ; Zero - Get another digit CONEXP: PUSH HL ; Save code string address LD A,E ; Get exponent SUB B ; Subtract digits after point SCALMI: CALL P,SCALPL ; Positive - Multiply number JP P,ENDCON ; Positive - All done PUSH AF ; Save number of times to /10 CALL DIV10 ; Divide by 10 POP AF ; Restore count INC A ; Count divides ; ENDCON: JP NZ,SCALMI ; More to do POP DE ; Restore code string address POP AF ; Restore sign of number CALL Z,INVSGN ; Negative - Negate number EX DE,HL ; Code string address to HL RET ; SCALPL: RET Z ; Exit if no scaling needed MULTEN: PUSH AF ; Save count CALL MLSP10 ; Multiply number by 10 POP AF ; Restore count DEC A ; Count multiplies RET ; ADDIG: PUSH DE ; Save sign of exponent LD D,A ; Save digit LD A,B ; Get digits after point ADC A,C ; Add one if after point LD B,A ; Re-save counter PUSH BC ; Save point flags PUSH HL ; Save code string address PUSH DE ; Save digit CALL MLSP10 ; Multiply number by 10 POP AF ; Restore digit SUB '0' ; Make it absolute CALL RSCALE ; Re-scale number POP HL ; Restore code string address POP BC ; Restore point flags POP DE ; Restore sign of exponent JP MANLP ; Get another digit ; RSCALE: CALL STAKFP ; Put number on stack CALL FLGREL ; Digit to add to FPREG PADD: POP BC ; Restore number POP DE JP FPADD ; Add BCDE to FPREG and return ; EDIGIT: LD A,E ; Get digit RLCA ; Times 2 RLCA ; Times 4 ADD A,E ; Times 5 RLCA ; Times 10 ADD A,(HL) ; Add next digit SUB '0' ; Make it absolute LD E,A ; Save new digit JP EXPLP ; Look for another digit ; LINEIN: PUSH HL ; Save code string address LD HL,INMSG ; Output " in " CALL PRS ; Output string at HL POP HL ; Restore code string address PRNTHL: EX DE,HL ; Code string address to DE XOR A LD B,80H+24 ; 24 bits CALL RETINT ; Return the integer LD HL,PRNUMS ; Print number string PUSH HL ; Save for return NUMASC: LD HL,PBUFF ; Convert number to ASCII PUSH HL ; Save for return CALL TSTSGN ; Test sign of FPREG LD (HL),' ' ; Space at start JP P,SPCFST ; Positive - Space to start LD (HL),'-' ; '-' sign at start SPCFST: INC HL ; First byte of number LD (HL),'0' ; '0' if zero JP Z,JSTZER ; Return '0' if zero PUSH HL ; Save buffer address CALL M,INVSGN ; Negate FPREG if negative XOR A ; Zero A PUSH AF ; Save it CALL RNGTST ; Test number is in range SIXDIG: LD BC,9143H ; BCDE - 99999.9 LD DE,4FF8H CALL CMPNUM ; Compare numbers OR A JP PO,INRNG ; > 99999.9 - Sort it out POP AF ; Restore count CALL MULTEN ; Multiply by ten PUSH AF ; Re-save count JP SIXDIG ; Test it again ; GTSIXD: CALL DIV10 ; Divide by 10 POP AF ; Get count INC A ; Count divides PUSH AF ; Re-save count CALL RNGTST ; Test number is in range INRNG: CALL ROUND ; Add 0.5 to FPREG INC A CALL FPINT ; F.P to integer CALL FPBCDE ; Move BCDE to FPREG LD BC,0306H ; 1E+06 to 1E-03 range POP AF ; Restore count ADD A,C ; 6 digits before point INC A ; Add one JP M,MAKNUM ; Do it in 'E' form if < 1E-02 CP 6+1+1 ; More than 999999 ? JP NC,MAKNUM ; Yes - Do it in 'E' form INC A ; Adjust for exponent LD B,A ; Exponent of number LD A,2 ; Make it zero after ; MAKNUM: DEC A ; Adjust for digits to do DEC A POP HL ; Restore buffer address PUSH AF ; Save count LD DE,POWERS ; Powers of ten DEC B ; Count digits before point JP NZ,DIGTXT ; Not zero - Do number LD (HL),'.' ; Save point INC HL ; Move on LD (HL),'0' ; Save zero INC HL ; Move on DIGTXT: DEC B ; Count digits before point LD (HL),'.' ; Save point in case CALL Z,INCHL ; Last digit - move on PUSH BC ; Save digits before point PUSH HL ; Save buffer address PUSH DE ; Save powers of ten CALL BCDEFP ; Move FPREG to BCDE POP HL ; Powers of ten table LD B, '0'-1 ; ASCII '0' - 1 TRYAGN: INC B ; Count subtractions LD A,E ; Get LSB SUB (HL) ; Subtract LSB LD E,A ; Save LSB INC HL LD A,D ; Get NMSB SBC A,(HL) ; Subtract NMSB LD D,A ; Save NMSB INC HL LD A,C ; Get MSB SBC A,(HL) ; Subtract MSB LD C,A ; Save MSB DEC HL ; Point back to start DEC HL JP NC,TRYAGN ; No overflow - Try again CALL PLUCDE ; Restore number INC HL ; Start of next number CALL FPBCDE ; Move BCDE to FPREG EX DE,HL ; Save point in table POP HL ; Restore buffer address LD (HL),B ; Save digit in buffer INC HL ; And move on POP BC ; Restore digit count DEC C ; Count digits JP NZ,DIGTXT ; More - Do them DEC B ; Any decimal part? JP Z,DOEBIT ; No - Do 'E' bit SUPTLZ: DEC HL ; Move back through buffer LD A,(HL) ; Get character CP '0' ; '0' character? JP Z,SUPTLZ ; Yes - Look back for more CP '.' ; A decimal point? CALL NZ,INCHL ; Move back over digit ; DOEBIT: POP AF ; Get 'E' flag JP Z,NOENED ; No 'E' needed - End buffer LD (HL),'E' ; Put 'E' in buffer INC HL ; And move on LD (HL),'+' ; Put '+' in buffer JP P,OUTEXP ; Positive - Output exponent LD (HL),'-' ; Put '-' in buffer CPL ; Negate exponent INC A OUTEXP: LD B,'0'-1 ; ASCII '0' - 1 EXPTEN: INC B ; Count subtractions SUB 10 ; Tens digit JP NC,EXPTEN ; More to do ADD A,'0'+10 ; Restore and make ASCII INC HL ; Move on LD (HL),B ; Save MSB of exponent JSTZER: INC HL ; LD (HL),A ; Save LSB of exponent INC HL NOENED: LD (HL),C ; Mark end of buffer POP HL ; Restore code string address RET ; RNGTST: LD BC,9474H ; BCDE = 999999. LD DE,23F7H CALL CMPNUM ; Compare numbers OR A POP HL ; Return address to HL JP PO,GTSIXD ; Too big - Divide by ten JP (HL) ; Otherwise return to caller ; HALF: DB 00H,00H,00H,80H ; 0.5 ; POWERS: DB 0A0H,086H,001H ; 100000 DB 010H,027H,000H ; 10000 DB 0E8H,003H,000H ; 1000 DB 064H,000H,000H ; 100 DB 00AH,000H,000H ; 10 DB 001H,000H,000H ; 1 ; NEGAFT: LD HL,INVSGN ; Negate result EX (SP),HL ; To be done after caller JP (HL) ; Return to caller ; SQR: CALL STAKFP ; Put value on stack LD HL,HALF ; Set power to 1/2 CALL PHLTFP ; Move 1/2 to FPREG ; POWER: POP BC ; Get base POP DE CALL TSTSGN ; Test sign of power LD A,B ; Get exponent of base JP Z,EXP ; Make result 1 if zero JP P,POWER1 ; Positive base - Ok OR A ; Zero to negative power? JP Z,DZERR ; Yes - ?/0 Error POWER1: OR A ; Base zero? JP Z,SAVEXP ; Yes - Return zero PUSH DE ; Save base PUSH BC LD A,C ; Get MSB of base OR 01111111B ; Get sign status CALL BCDEFP ; Move power to BCDE JP P,POWER2 ; Positive base - Ok PUSH DE ; Save power PUSH BC CALL INT ; Get integer of power POP BC ; Restore power POP DE PUSH AF ; MSB of base CALL CMPNUM ; Power an integer? POP HL ; Restore MSB of base LD A,H ; but don't affect flags RRA ; Exponent odd or even? POWER2: POP HL ; Restore MSB and exponent LD (FPREG+2),HL ; Save base in FPREG POP HL ; LSBs of base LD (FPREG),HL ; Save in FPREG CALL C,NEGAFT ; Odd power - Negate result CALL Z,INVSGN ; Negative base - Negate it PUSH DE ; Save power PUSH BC CALL LOG ; Get LOG of base POP BC ; Restore power POP DE CALL FPMULT ; Multiply LOG by power ; EXP: CALL STAKFP ; Put value on stack LD BC,08138H ; BCDE = 1/Ln(2) LD DE,0AA3BH CALL FPMULT ; Multiply value by 1/LN(2) LD A,(FPEXP) ; Get exponent CP 80H+8 ; Is it in range? JP NC,OVTST1 ; No - Test for overflow CALL INT ; Get INT of FPREG ADD A,80H ; For excess 128 ADD A,2 ; Exponent > 126? JP C,OVTST1 ; Yes - Test for overflow PUSH AF ; Save scaling factor LD HL,UNITY ; Point to 1. CALL ADDPHL ; Add 1 to FPREG CALL MULLN2 ; Multiply by LN(2) POP AF ; Restore scaling factor POP BC ; Restore exponent POP DE PUSH AF ; Save scaling factor CALL SUBCDE ; Subtract exponent from FPREG CALL INVSGN ; Negate result LD HL,EXPTAB ; Coefficient table CALL SMSER1 ; Sum the series LD DE,0 ; Zero LSBs POP BC ; Scaling factor LD C,D ; Zero MSB JP FPMULT ; Scale result to correct value ; EXPTAB: DB 8 ; Table used by EXP DB 040H,02EH,094H,074H ; -1/7! (-1/5040) DB 070H,04FH,02EH,077H ; 1/6! ( 1/720) DB 06EH,002H,088H,07AH ; -1/5! (-1/120) DB 0E6H,0A0H,02AH,07CH ; 1/4! ( 1/24) DB 050H,0AAH,0AAH,07EH ; -1/3! (-1/6) DB 0FFH,0FFH,07FH,07FH ; 1/2! ( 1/2) DB 000H,000H,080H,081H ; -1/1! (-1/1) DB 000H,000H,000H,081H ; 1/0! ( 1/1) ; SUMSER: CALL STAKFP ; Put FPREG on stack LD DE,MULT ; Multiply by "X" PUSH DE ; To be done after PUSH HL ; Save address of table CALL BCDEFP ; Move FPREG to BCDE CALL FPMULT ; Square the value POP HL ; Restore address of table SMSER1: CALL STAKFP ; Put value on stack LD A,(HL) ; Get number of coefficients INC HL ; Point to start of table CALL PHLTFP ; Move coefficient to FPREG DB 06H ; Skip "POP AF" SUMLP: POP AF ; Restore count POP BC ; Restore number POP DE DEC A ; Cont coefficients RET Z ; All done PUSH DE ; Save number PUSH BC PUSH AF ; Save count PUSH HL ; Save address in table CALL FPMULT ; Multiply FPREG by BCDE POP HL ; Restore address in table CALL LOADFP ; Number at HL to BCDE PUSH HL ; Save address in table CALL FPADD ; Add coefficient to FPREG POP HL ; Restore address in table JP SUMLP ; More coefficients ; RND: CALL TSTSGN ; Test sign of FPREG LD HL,SEED+2 ; Random number seed JP M,RESEED ; Negative - Re-seed LD HL,LSTRND ; Last random number CALL PHLTFP ; Move last RND to FPREG LD HL,SEED+2 ; Random number seed RET Z ; Return if RND(0) ADD A,(HL) ; Add (SEED)+2) AND 00000111B ; 0 to 7 LD B,0 LD (HL),A ; Re-save seed INC HL ; Move to coefficient table ADD A,A ; 4 bytes ADD A,A ; per entry LD C,A ; BC = Offset into table ADD HL,BC ; Point to coefficient CALL LOADFP ; Coefficient to BCDE CALL FPMULT ; ; Multiply FPREG by coefficient LD A,(SEED+1) ; Get (SEED+1) INC A ; Add 1 AND 00000011B ; 0 to 3 LD B,0 CP 1 ; Is it zero? ADC A,B ; Yes - Make it 1 LD (SEED+1),A ; Re-save seed LD HL,RNDTAB-4 ; Addition table ADD A,A ; 4 bytes ADD A,A ; per entry LD C,A ; BC = Offset into table ADD HL,BC ; Point to value CALL ADDPHL ; Add value to FPREG RND1: CALL BCDEFP ; Move FPREG to BCDE LD A,E ; Get LSB LD E,C ; LSB = MSB XOR 01001111B ; Fiddle around LD C,A ; New MSB LD (HL),80H ; Set exponent DEC HL ; Point to MSB LD B,(HL) ; Get MSB LD (HL),80H ; Make value -0.5 LD HL,SEED ; Random number seed INC (HL) ; Count seed LD A,(HL) ; Get seed SUB 171 ; Do it modulo 171 JP NZ,RND2 ; Non-zero - Ok LD (HL),A ; Zero seed INC C ; Fillde about DEC D ; with the INC E ; number RND2: CALL BNORM ; Normalise number LD HL,LSTRND ; Save random number JP FPTHL ; Move FPREG to last and return ; RESEED: LD (HL),A ; Re-seed random numbers DEC HL LD (HL),A DEC HL LD (HL),A JP RND1 ; Return RND seed ; RNDTAB: DB 068H,0B1H,046H,068H ; Table used by RND DB 099H,0E9H,092H,069H DB 010H,0D1H,075H,068H ; COS: LD HL,HALFPI ; Point to PI/2 CALL ADDPHL ; Add it to PPREG SIN: CALL STAKFP ; Put angle on stack LD BC,8349H ; BCDE = 2 PI LD DE,0FDBH CALL FPBCDE ; Move 2 PI to FPREG POP BC ; Restore angle POP DE CALL DVBCDE ; Divide angle by 2 PI CALL STAKFP ; Put it on stack CALL INT ; Get INT of result POP BC ; Restore number POP DE CALL SUBCDE ; Make it 0 <= value < 1 LD HL,QUARTR ; Point to 0.25 CALL SUBPHL ; Subtract value from 0.25 CALL TSTSGN ; Test sign of value SCF ; Flag positive JP P,SIN1 ; Positive - Ok CALL ROUND ; Add 0.5 to value CALL TSTSGN ; Test sign of value OR A ; Flag negative SIN1: PUSH AF ; Save sign CALL P,INVSGN ; Negate value if positive LD HL,QUARTR ; Point to 0.25 CALL ADDPHL ; Add 0.25 to value POP AF ; Restore sign CALL NC,INVSGN ; Negative - Make positive LD HL,SINTAB ; Coefficient table JP SUMSER ; Evaluate sum of series ; HALFPI: DB 0DBH,00FH,049H,081H ; 1.5708 (PI/2) ; QUARTR: DB 000H,000H,000H,07FH ; 0.25 ; SINTAB: DB 5 ; Table used by SIN DB 0BAH,0D7H,01EH,086H ; 39.711 DB 064H,026H,099H,087H ;-76.575 DB 058H,034H,023H,087H ; 81.602 DB 0E0H,05DH,0A5H,086H ;-41.342 DB 0DAH,00FH,049H,083H ; 6.2832 ; TAN: CALL STAKFP ; Put angle on stack CALL SIN ; Get SIN of angle POP BC ; Restore angle POP HL CALL STAKFP ; Save SIN of angle EX DE,HL ; BCDE = Angle CALL FPBCDE ; Angle to FPREG CALL COS ; Get COS of angle JP DIV ; TAN = SIN / COS ; ATN: CALL TSTSGN ; Test sign of value CALL M,NEGAFT ; Negate result after if -ve CALL M,INVSGN ; Negate value if -ve LD A,(FPEXP) ; Get exponent CP 81H ; Number less than 1? JP C,ATN1 ; Yes - Get arc tangnt LD BC,8100H ; BCDE = 1 LD D,C LD E,C CALL DVBCDE ; Get reciprocal of number LD HL,SUBPHL ; Sub angle from PI/2 PUSH HL ; Save for angle > 1 ATN1: LD HL,ATNTAB ; Coefficient table CALL SUMSER ; Evaluate sum of series LD HL,HALFPI ; PI/2 - angle in case > 1 RET ; Number > 1 - Sub from PI/2 ; ATNTAB: DB 9 ; Table used by ATN DB 04AH,0D7H,03BH,078H ; 1/17 DB 002H,06EH,084H,07BH ;-1/15 DB 0FEH,0C1H,02FH,07CH ; 1/13 DB 074H,031H,09AH,07DH ;-1/11 DB 084H,03DH,05AH,07DH ; 1/9 DB 0C8H,07FH,091H,07EH ;-1/7 DB 0E4H,0BBH,04CH,07EH ; 1/5 DB 06CH,0AAH,0AAH,07FH ;-1/3 DB 000H,000H,000H,081H ; 1/1 ; ARET: RET ; A RETurn instruction ; GETINP: RST 10H ;input a character RET ; CLS: LD A,CS ; ASCII Clear screen JP MONOUT ; Output character ; WIDTH: CALL GETINT ; Get integer 0-255 LD A,E ; Width to A LD (LWIDTH),A ; Set width RET ; LINES: CALL GETNUM ; Get a number CALL DEINT ; Get integer -32768 to 32767 LD (LINESC),DE ; Set lines counter LD (LINESN),DE ; Set lines number RET ; DEEK: CALL DEINT ; Get integer -32768 to 32767 PUSH DE ; Save number POP HL ; Number to HL LD B,(HL) ; Get LSB of contents INC HL LD A,(HL) ; Get MSB of contents JP ABPASS ; Return integer AB ; DOKE: CALL GETNUM ; Get a number CALL DEINT ; Get integer -32768 to 32767 PUSH DE ; Save address CALL CHKSYN ; Make sure ',' follows DB ',' CALL GETNUM ; Get a number CALL DEINT ; Get integer -32768 to 32767 EX (SP),HL ; Save value,get address LD (HL),E ; Save LSB of value INC HL LD (HL),D ; Save MSB of value POP HL ; Restore code string address RET ; ; HEX$(nn) Convert 16 bit number to Hexadecimal string ; HEX: CALL TSTNUM ; Verify it's a number CALL DEINT ; Get integer -32768 to 32767 PUSH BC ; Save contents of BC LD HL,PBUFF LD A,D ; Get high order into A CP 0 JR Z,HEX2 ; Skip output if both high digits are zero CALL BYT2ASC ; Convert D to ASCII LD A,B CP '0' JR Z,HEX1 ; Don't store high digit if zero LD (HL),B ; Store it to PBUFF INC HL ; Next location HEX1: LD (HL),C ; Store C to PBUFF+1 INC HL ; Next location HEX2: LD A,E ; Get lower byte CALL BYT2ASC ; Convert E to ASCII LD A,D CP 0 JR NZ,HEX3 ; If upper byte was not zero then always print lower byte LD A,B CP '0' ; If high digit of lower byte is zero then don't print JR Z,HEX4 HEX3: LD (HL),B ; to PBUFF+2 INC HL ; Next location HEX4: LD (HL),C ; to PBUFF+3 INC HL ; PBUFF+4 to zero XOR A ; Terminating character LD (HL),A ; Store zero to terminate INC HL ; Make sure PBUFF is terminated LD (HL),A ; Store the double zero there POP BC ; Get BC back LD HL,PBUFF ; Reset to start of PBUFF JP STR1 ; Convert the PBUFF to a string and return it ; BYT2ASC LD B,A ; Save original value AND 0FH ; Strip off upper nybble CP 0AH ; 0-9? JR C,ADD30 ; If A-F, add 7 more ADD A,07H ; Bring value up to ASCII A-F ADD30 ADD A,30H ; And make ASCII LD C,A ; Save converted char to C LD A,B ; Retrieve original value RRCA ; and Rotate it right RRCA RRCA RRCA AND 0FH ; Mask off upper nybble CP 0AH ; 0-9? < A hex? JR C,ADD301 ; Skip Add 7 ADD A,07H ; Bring it up to ASCII A-F ADD301 ADD A,30H ; And make it full ASCII LD B,A ; Store high order byte RET ; ; Convert "&Hnnnn" to FPREG ; Gets a character from (HL) checks for Hexadecimal ASCII numbers "&Hnnnn" ; Char is in A, NC if char is;<=>?@ A-z, CY is set if 0-9 HEXTFP EX DE,HL ; Move code string pointer to DE LD HL,0000H ; Zero out the value CALL GETHEX ; Check the number for valid hex JP C,HXERR ; First value wasn't hex, HX error JR HEXLP1 ; Convert first character HEXLP CALL GETHEX ; Get second and addtional characters JR C,HEXIT ; Exit if not a hex character HEXLP1 ADD HL,HL ; Rotate 4 bits to the left ADD HL,HL ADD HL,HL ADD HL,HL OR L ; Add in D0-D3 into L LD L,A ; Save new value JR HEXLP ; And continue until all hex characters are in ; GETHEX INC DE ; Next location LD A,(DE) ; Load character at pointer CP ' ' JP Z,GETHEX ; Skip spaces SUB 30H ; Get absolute value RET C ; < "0", error CP 0AH JR C,NOSUB7 ; Is already in the range 0-9 SUB 07H ; Reduce to A-F CP 0AH ; Value should be $0A-$0F at this point RET C ; CY set if was : ; < = > ? @ NOSUB7 CP 10H ; > Greater than "F"? CCF RET ; CY set if it wasn't valid hex HEXIT EX DE,HL ; Value into DE, Code string into HL LD A,D ; Load DE into AC LD C,E ; For prep to PUSH HL CALL ACPASS ; ACPASS to set AC as integer into FPREG POP HL RET ; HXERR: LD E,HX ; ?HEX Error JP ERROR ; ; BIN$(NN) Convert integer to a 1-16 char binary string BIN: CALL TSTNUM ; Verify it's a number CALL DEINT ; Get integer -32768 to 32767 BIN2: PUSH BC ; Save contents of BC LD HL,PBUFF LD B,17 ; One higher than max char count ZEROSUP: ; Suppress leading zeros DEC B ; Max 16 chars LD A,B CP 01H JR Z,BITOUT ; Always output at least one character RL E RL D JR NC,ZEROSUP JR BITOUT2 BITOUT: RL E RL D ; Top bit now in carry BITOUT2: LD A,'0' ; Char for '0' ADC A,0 ; If carry set then '0' --> '1' LD (HL),A INC HL DEC B JR NZ,BITOUT XOR A ; Terminating character LD (HL),A ; Store zero to terminate INC HL ; Make sure PBUFF is terminated LD (HL),A ; Store the double zero there POP BC LD HL,PBUFF JP STR1 ; ; Convert "&Bnnnn" to FPREG ; Gets a character from (HL) checks for Binary ASCII numbers "&Bnnnn" BINTFP: EX DE,HL ; Move code string pointer to DE LD HL,0000H ; Zero out the value CALL CHKBIN ; Check the number for valid bin JP C,BINERR ; First value wasn't bin, HX error BINIT: SUB '0' ADD HL,HL ; Rotate HL left OR L LD L,A CALL CHKBIN ; Get second and addtional characters JR NC,BINIT ; Process if a bin character EX DE,HL ; Value into DE, Code string into HL LD A,D ; Load DE into AC LD C,E ; For prep to PUSH HL CALL ACPASS ; ACPASS to set AC as integer into FPREG POP HL RET ; ; Char is in A, NC if char is 0 or 1 CHKBIN: INC DE LD A,(DE) CP ' ' JP Z,CHKBIN ; Skip spaces CP '0' ; Set C if < '0' RET C CP '2' CCF ; Set C if > '1' RET ; BINERR: LD E,BN ; ?BIN Error JP ERROR ; JJUMP1: JP CSTART ; Go and initialise ; MONOUT: JP 0008H ; output a char ; MONITR: JP 0000H ; Restart (Normally Monitor Start) ; INITST: LD A,0 ; Clear break flag LD (BRKFLG),A JP INIT ; TSTBIT: PUSH AF ; Save bit mask AND B ; Get common bits POP BC ; Restore bit mask CP B ; Same bit set? LD A,0 ; Return 0 in A RET ; OUTNCR: CALL OUTC ; Output character in A JP PRCRLF ; Output CRLF ; ; ; CLOCK: LD HL,0 ; Clock Entrance LD (MS),HL ; Clear MS LD (DAY),HL ; Clear Day XOR A LD (SEC),A ; Clear Second LD (MIN),A ; Clear Minute LD (HOR),A ; Clear Hour LD HL,VECTOR ; Set M2 Interrupt Table LD A,H LD I,A ; Set M2 Upper Address IM 2 LD A,0A7H ; Set Timer Mode OUT (CTC0),A if (HZ=12) LD A,240 ;10MHz 192, 12MHz 240 Set 5ms Interval else LD A,192 endif OUT (CTC0),A LD A,L ; M2 Lower Address OUT (CTC0),A EI RET INTX: PUSH AF ; Timer Routine PUSH BC PUSH HL LD HL,(MS) LD BC,5 ADD HL,BC LD BC,1000 LD A,H CP B JR NZ,INT9 LD A,L CP C JR NZ,INT9 LD A,(SEC) INC A LD (SEC),A CP 60 JR NZ,INT8 LD A,(MIN) INC A LD (MIN),A CP 60 JR NZ,INT7 LD A,(HOR) INC A LD (HOR),A CP 24 JR NZ,INT6 LD HL,(DAY) INC HL LD (DAY),HL INT5: XOR A LD (HOR),A INT6: XOR A LD (MIN),A INT7: XOR A LD (SEC),A INT8: LD HL,0 INT9: LD (MS),HL POP HL POP BC POP AF EI RETI ; ; PIOINITA: LD A,0CFH ; Port A Mode 3 OUT (PIOA+1),A LD A,(PADIR) ; I/O Direction OUT (PIOA+1),A LD A,07H ; None Interrupt OUT (PIOA+1),A RET PIOINITB: LD A,0CFH ; Port B Mode 3 OUT (PIOB+1),A LD A,(PBDIR) ; I/O Direction OUT (PIOB+1),A LD A,07H ; None Interrupt OUT (PIOB+1),A RET ; ; PA: CALL PIOINITA LD A,(PADT) OUT (PIOA),A RET PB: CALL PIOINITB LD A,(PBDT) OUT (PIOB),A RET PP: CALL GETINT OR A JR Z,TORAM ;ROM to RAM CP 1H ;PIOA JR Z,PA CP 2H ;PIOB JR Z,PB CP 3H JR Z,TORAM RET TORAM: LD HL,ONRAM LD DE,0C000H LD BC,ONRAM1-ONRAM LDIR JP 0C000H ONRAM: DB 03EH,005H,0D3H,01BH DB 03EH,0EAH,0D3H,01BH db 000H,000H,000H,000H DB 0C3H,000H,000H,000H ONRAM1: ; ; LOAD: PUSH DE PUSH HL PUSH BC LD HL,HEXMSG ; Sign-on message CALL PRS ; Output string LCMD0: RST 10H CP CTRLC ; Is it control "C"? CALL Z,PRCRLF ; Yes - Output CRLF SCF ; Flag break JP Z,BRK ; Return if control "C" CP ":" JR NZ,LCMD0 LCMD1: LD C,0 RST 10H ;Length CALL ATOH2 JP C,HEXERR ADD A,A ADD A,A ADD A,A ADD A,A LD D,A RST 10H CALL ATOH2 JP C,HEXERR ADD A,D LD B,A ;Save TXT Length LD C,A RST 10H ;Address CALL ATOH2 JP C,HEXERR ADD A,A ADD A,A ADD A,A ADD A,A LD D,A RST 10H CALL ATOH2 JP C,HEXERR ADD A,D LD H,A ;Set Upper Address ADD A,C LD C,A RST 10H CALL ATOH2 JP C,HEXERR ADD A,A ADD A,A ADD A,A ADD A,A LD D,A RST 10H CALL ATOH2 JP C,HEXERR ADD A,D LD L,A ;Set Lower Address ADD A,C LD C,A RST 10H CALL ATOH2 JP C,HEXERR ADD A,A ADD A,A ADD A,A ADD A,A LD D,A ;Skip RST 10H CALL ATOH2 JP C,HEXERR ADD A,D CP 01H JP Z,HEXEND LCMD3: RST 10H ;Data CALL ATOH2 JP C,HEXERR ADD A,A ADD A,A ADD A,A ADD A,A LD D,A RST 10H CALL ATOH2 JP C,HEXERR ADD A,D LD (HL),A ADD A,C LD C,A INC HL DJNZ LCMD3 LD A,C CPL INC A LD C,A RST 10H CALL ATOH2 JP C,HEXERR ADD A,A ADD A,A ADD A,A ADD A,A LD D,A RST 10H CALL ATOH2 JP C,HEXERR ADD A,D CP C JP NZ,HEXERR LD A,'*' ;+************ RST 08H JP LCMD0 HEXERR: LD HL,HEXMS1 ; Sign-on message CALL PRS ; Output string POP BC POP HL POP DE JP COLD HEXEND: RST 10H CP 0DH JR NZ,HEXEND CALL PRCRLF LD HL,HEXMS2 ; Sign-on message CALL PRS ; Output string POP BC POP HL POP DE JP COLD HEXMSG: DB 'READY' DB cr,lf,0,0 HEXMS1: DB 'FAILED' DB cr,lf,0,0 HEXMS2: DB 'ENDED' DB cr,lf,0,0 ATOH2: CP '0' RET C CP '9'+1 JR C,ATOHO CP 'A' RET C CP 'F'+1 CCF RET C ADD A,09H ATOHO: AND 0FH RET WHTREG: PUSH AF PUSH BC PUSH DE PUSH HL LD (AFREG),A LD (BCREG),BC LD (DEREG),DE LD (HLREG),HL POP HL POP DE POP BC POP AF RET BSRAM: ;0000H DB 0F3H, 0C3H, 0A7H, 000H, 0FFH, 0FFH, 0FFH, 0FFH, 0C3H, 072H, 000H, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH DB 0C3H, 04CH, 000H, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0C3H, 07DH, 000H, 0F3H, 0F5H, 0C5H, 0D5H, 0E5H DB 0DBH, 019H, 0CBH, 047H, 028H, 01FH, 0DBH, 018H, 057H, 03AH, 000H, 081H, 0FEH, 040H, 028H, 015H DB 03CH, 032H, 000H, 081H, 03AH, 002H, 081H, 04FH, 006H, 000H, 021H, 003H, 081H, 009H, 072H, 03CH DB 0E6H, 03FH, 032H, 002H, 081H, 0E1H, 0D1H, 0C1H, 0F1H, 0FBH, 0EDH, 04DH, 0C5H, 0D5H, 0E5H, 03AH DB 000H, 081H, 0FEH, 000H, 028H, 0F9H, 0F3H, 03DH, 032H, 000H, 081H, 03AH, 001H, 081H, 04FH, 006H DB 000H, 021H, 003H, 081H, 009H, 056H, 03CH, 0E6H, 03FH, 032H, 001H, 081H, 07AH, 0FBH, 0E1H, 0D1H DB 0C1H, 0C9H, 0F5H, 0DBH, 019H, 0CBH, 057H, 028H, 0FAH, 0F1H, 0D3H, 018H, 0C9H, 03AH, 000H, 081H DB 0FEH, 000H, 0C9H, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH DB 07EH, 01DH, 000H, 000H, 000H, 000H, 000H, 000H, 01BH, 000H, 018H, 001H, 010H, 004H, 044H, 005H DB 0EAH, 003H, 0C1H, 001H, 000H, 002H, 098H, 031H, 0EDH, 080H, 0AFH, 032H, 000H, 081H, 032H, 001H DB 081H, 032H, 002H, 081H, 03EH, 007H, 0D3H, 013H, 03EH, 004H, 0D3H, 013H, 006H, 009H, 00EH, 019H DB 021H, 09AH, 000H, 0EDH, 0B3H, 006H, 004H, 00EH, 01BH, 021H, 0A3H, 000H, 0EDH, 0B3H, 021H, 098H DB 000H, 07CH, 0EDH, 047H, 0EDH, 05EH, 0FBH, 0CDH, 056H, 01DH, 0C3H, 0DDH, 000H, 0C3H, 0E3H, 000H DB 0C3H, 06AH, 001H, 0C3H, 0EAH, 000H, 0B0H, 009H, 026H, 011H, 021H, 045H, 021H, 0F9H, 03EH, 002H DB 032H, 000H, 020H, 0AFH, 032H, 007H, 020H, 032H, 006H, 020H, 032H, 005H, 020H, 032H, 004H, 020H ;0100H DB 0C3H, 041H, 01DH, 011H, 0D7H, 003H, 006H, 063H, 021H, 045H, 021H, 01AH, 077H, 023H, 013H, 005H DB 0C2H, 00BH, 001H, 0F9H, 0CDH, 0D8H, 005H, 0CDH, 0A6H, 00BH, 032H, 0EFH, 021H, 032H, 03EH, 022H DB 021H, 0A2H, 022H, 023H, 07CH, 0B5H, 0CAH, 032H, 001H, 07EH, 047H, 02FH, 077H, 0BEH, 070H, 0CAH DB 023H, 001H, 02BH, 011H, 0A1H, 022H, 0CDH, 06EH, 007H, 0DAH, 073H, 001H, 011H, 0CEH, 0FFH, 022H DB 0F4H, 021H, 019H, 022H, 09FH, 021H, 0CDH, 0B3H, 005H, 02AH, 09FH, 021H, 011H, 0EFH, 0FFH, 019H DB 011H, 03EH, 022H, 07DH, 093H, 06FH, 07CH, 09AH, 067H, 0E5H, 021H, 08BH, 001H, 0CDH, 044H, 012H DB 0E1H, 0CDH, 0E7H, 018H, 021H, 07CH, 001H, 0CDH, 044H, 012H, 031H, 0ABH, 021H, 0CDH, 0D8H, 005H DB 0C3H, 0F1H, 004H, 021H, 0C9H, 001H, 0CDH, 044H, 012H, 0C3H, 079H, 001H, 020H, 042H, 079H, 074H DB 065H, 073H, 020H, 066H, 072H, 065H, 065H, 00DH, 00AH, 000H, 000H, 05AH, 038H, 030H, 020H, 042H DB 041H, 053H, 049H, 043H, 020H, 056H, 065H, 072H, 020H, 034H, 02EH, 037H, 062H, 00DH, 00AH, 043H DB 06FH, 070H, 079H, 072H, 069H, 067H, 068H, 074H, 020H, 028H, 043H, 029H, 020H, 031H, 039H, 037H DB 038H, 020H, 062H, 079H, 020H, 04DH, 069H, 063H, 072H, 06FH, 073H, 06FH, 066H, 074H, 020H, 06FH DB 06EH, 020H, 052H, 041H, 04DH, 00DH, 00AH, 000H, 000H, 04DH, 065H, 06DH, 06FH, 072H, 079H, 020H DB 073H, 069H, 07AH, 065H, 020H, 06EH, 06FH, 074H, 020H, 065H, 06EH, 06FH, 075H, 067H, 068H, 00DH DB 00AH, 054H, 068H, 065H, 020H, 073H, 079H, 073H, 074H, 065H, 06DH, 020H, 069H, 073H, 020H, 073H DB 074H, 06FH, 070H, 070H, 065H, 064H, 02EH, 00DH, 00AH, 000H, 000H, 05CH, 017H, 020H, 018H, 072H ;0200H DB 017H, 048H, 021H, 004H, 011H, 089H, 014H, 032H, 011H, 0E6H, 019H, 0C5H, 01AH, 001H, 016H, 034H DB 01AH, 03AH, 01BH, 040H, 01BH, 0A1H, 01BH, 0B6H, 01BH, 0DDH, 014H, 021H, 01CH, 096H, 021H, 0B6H DB 013H, 0CEH, 011H, 050H, 014H, 0C5H, 013H, 0D6H, 013H, 043H, 01CH, 0D6H, 01CH, 0E6H, 013H, 016H DB 014H, 020H, 014H, 0C5H, 04EH, 044H, 0C6H, 04FH, 052H, 0CEH, 045H, 058H, 054H, 0C4H, 041H, 054H DB 041H, 0C9H, 04EH, 050H, 055H, 054H, 0C4H, 049H, 04DH, 0D2H, 045H, 041H, 044H, 0CCH, 045H, 054H DB 0C7H, 04FH, 054H, 04FH, 0D2H, 055H, 04EH, 0C9H, 046H, 0D2H, 045H, 053H, 054H, 04FH, 052H, 045H DB 0C7H, 04FH, 053H, 055H, 042H, 0D2H, 045H, 054H, 055H, 052H, 04EH, 0D2H, 045H, 04DH, 0D3H, 054H DB 04FH, 050H, 0CFH, 055H, 054H, 0CFH, 04EH, 0CEH, 055H, 04CH, 04CH, 0D7H, 041H, 049H, 054H, 0C4H DB 045H, 046H, 0D0H, 04FH, 04BH, 045H, 0C4H, 04FH, 04BH, 045H, 0D3H, 043H, 052H, 045H, 045H, 04EH DB 0CCH, 049H, 04EH, 045H, 053H, 0C3H, 04CH, 053H, 0D7H, 049H, 044H, 054H, 048H, 0CDH, 04FH, 04EH DB 049H, 054H, 04FH, 052H, 0D3H, 045H, 054H, 0D2H, 045H, 053H, 045H, 054H, 0D0H, 052H, 049H, 04EH DB 054H, 0C3H, 04FH, 04EH, 054H, 0CCH, 049H, 053H, 054H, 0C3H, 04CH, 045H, 041H, 052H, 0D0H, 050H DB 0CCH, 04FH, 041H, 044H, 0CEH, 045H, 057H, 0D4H, 041H, 042H, 028H, 0D4H, 04FH, 0C6H, 04EH, 0D3H DB 050H, 043H, 028H, 0D4H, 048H, 045H, 04EH, 0CEH, 04FH, 054H, 0D3H, 054H, 045H, 050H, 0ABH, 0ADH DB 0AAH, 0AFH, 0DEH, 0C1H, 04EH, 044H, 0CFH, 052H, 0BEH, 0BDH, 0BCH, 0D3H, 047H, 04EH, 0C9H, 04EH DB 054H, 0C1H, 042H, 053H, 0D5H, 053H, 052H, 0C6H, 052H, 045H, 0C9H, 04EH, 050H, 0D0H, 04FH, 053H ;0300H DB 0D3H, 051H, 052H, 0D2H, 04EH, 044H, 0CCH, 04FH, 047H, 0C5H, 058H, 050H, 0C3H, 04FH, 053H, 0D3H DB 049H, 04EH, 0D4H, 041H, 04EH, 0C1H, 054H, 04EH, 0D0H, 045H, 045H, 04BH, 0C4H, 045H, 045H, 04BH DB 0D0H, 04FH, 049H, 04EH, 054H, 0CCH, 045H, 04EH, 0D3H, 054H, 052H, 024H, 0D6H, 041H, 04CH, 0C1H DB 053H, 043H, 0C3H, 048H, 052H, 024H, 0C8H, 045H, 058H, 024H, 0C2H, 049H, 04EH, 024H, 0CCH, 045H DB 046H, 054H, 024H, 0D2H, 049H, 047H, 048H, 054H, 024H, 0CDH, 049H, 044H, 024H, 080H, 048H, 009H DB 045H, 008H, 020H, 00DH, 095H, 00AH, 027H, 00CH, 05CH, 00FH, 056H, 00CH, 0ACH, 00AH, 052H, 00AH DB 035H, 00AH, 024H, 00BH, 00EH, 009H, 041H, 00AH, 070H, 00AH, 097H, 00AH, 046H, 009H, 095H, 014H DB 006H, 00BH, 087H, 009H, 09BH, 014H, 03AH, 011H, 0E4H, 014H, 02CH, 01CH, 097H, 00AH, 012H, 01CH DB 005H, 01CH, 00AH, 01CH, 03EH, 01DH, 099H, 021H, 09CH, 021H, 048H, 00BH, 074H, 009H, 0BAH, 007H DB 0EFH, 009H, 001H, 01EH, 01DH, 01EH, 0B2H, 005H, 079H, 0CEH, 018H, 079H, 002H, 015H, 07CH, 040H DB 016H, 07CH, 0A1H, 016H, 07FH, 0EFH, 019H, 050H, 0B5H, 00EH, 046H, 0B4H, 00EH, 04EH, 046H, 053H DB 04EH, 052H, 047H, 04FH, 044H, 046H, 043H, 04FH, 056H, 04FH, 04DH, 055H, 04CH, 042H, 053H, 044H DB 044H, 02FH, 030H, 049H, 044H, 054H, 04DH, 04FH, 053H, 04CH, 053H, 053H, 054H, 043H, 04EH, 055H DB 046H, 04DH, 04FH, 048H, 058H, 042H, 04EH, 0C3H, 06AH, 001H, 0C3H, 0C5H, 009H, 0D3H, 000H, 0C9H DB 0D6H, 000H, 06FH, 07CH, 0DEH, 000H, 067H, 078H, 0DEH, 000H, 047H, 03EH, 000H, 0C9H, 000H, 000H DB 000H, 035H, 04AH, 0CAH, 099H, 039H, 01CH, 076H, 098H, 022H, 095H, 0B3H, 098H, 00AH, 0DDH, 047H ;0400H DB 098H, 053H, 0D1H, 099H, 099H, 00AH, 01AH, 09FH, 098H, 065H, 0BCH, 0CDH, 098H, 0D6H, 077H, 03EH DB 098H, 052H, 0C7H, 04FH, 080H, 0DBH, 000H, 0C9H, 001H, 0FFH, 01CH, 000H, 000H, 014H, 000H, 014H DB 000H, 000H, 000H, 000H, 000H, 0C3H, 0EBH, 006H, 0C3H, 000H, 000H, 0C3H, 000H, 000H, 0C3H, 000H DB 000H, 0A2H, 022H, 0FEH, 0FFH, 03FH, 022H, 020H, 045H, 072H, 072H, 06FH, 072H, 000H, 020H, 069H DB 06EH, 020H, 000H, 04FH, 06BH, 00DH, 00AH, 000H, 000H, 042H, 072H, 065H, 061H, 06BH, 000H, 021H DB 004H, 000H, 039H, 07EH, 023H, 0FEH, 081H, 0C0H, 04EH, 023H, 046H, 023H, 0E5H, 069H, 060H, 07AH DB 0B3H, 0EBH, 0CAH, 069H, 004H, 0EBH, 0CDH, 06EH, 007H, 001H, 00DH, 000H, 0E1H, 0C8H, 009H, 0C3H DB 053H, 004H, 0CDH, 08CH, 004H, 0C5H, 0E3H, 0C1H, 0CDH, 06EH, 007H, 07EH, 002H, 0C8H, 00BH, 02BH DB 0C3H, 078H, 004H, 0E5H, 02AH, 01FH, 022H, 006H, 000H, 009H, 009H, 03EH, 0E5H, 03EH, 0D0H, 095H DB 06FH, 03EH, 0FFH, 09CH, 0DAH, 09BH, 004H, 067H, 039H, 0E1H, 0D8H, 01EH, 00CH, 0C3H, 0BAH, 004H DB 02AH, 00EH, 022H, 022H, 0A1H, 021H, 01EH, 002H, 001H, 01EH, 014H, 001H, 01EH, 000H, 001H, 01EH DB 012H, 001H, 01EH, 022H, 001H, 01EH, 00AH, 001H, 01EH, 018H, 0CDH, 0D8H, 005H, 032H, 08AH, 021H DB 0CDH, 099H, 00BH, 021H, 0ADH, 003H, 057H, 03EH, 03FH, 0CDH, 07FH, 007H, 019H, 07EH, 0CDH, 07FH DB 007H, 0CDH, 0FEH, 008H, 0CDH, 07FH, 007H, 021H, 037H, 004H, 0CDH, 044H, 012H, 02AH, 0A1H, 021H DB 011H, 0FEH, 0FFH, 0CDH, 06EH, 007H, 0CAH, 0EAH, 000H, 07CH, 0A5H, 03CH, 0C4H, 0DFH, 018H, 03EH DB 0C1H, 0AFH, 032H, 08AH, 021H, 0CDH, 099H, 00BH, 021H, 043H, 004H, 0CDH, 044H, 012H, 021H, 0FFH ;0500H DB 0FFH, 022H, 0A1H, 021H, 0CDH, 0EBH, 006H, 0DAH, 0FEH, 004H, 0CDH, 0FEH, 008H, 03CH, 03DH, 0CAH DB 0FEH, 004H, 0F5H, 0CDH, 0CAH, 009H, 0D5H, 0CDH, 002H, 006H, 047H, 0D1H, 0F1H, 0D2H, 0DEH, 008H DB 0D5H, 0C5H, 0AFH, 032H, 011H, 022H, 0CDH, 0FEH, 008H, 0B7H, 0F5H, 0CDH, 092H, 005H, 0DAH, 037H DB 005H, 0F1H, 0F5H, 0CAH, 06BH, 00AH, 0B7H, 0C5H, 0D2H, 04EH, 005H, 0EBH, 02AH, 01BH, 022H, 01AH DB 002H, 003H, 013H, 0CDH, 06EH, 007H, 0C2H, 03FH, 005H, 060H, 069H, 022H, 01BH, 022H, 0D1H, 0F1H DB 0CAH, 075H, 005H, 02AH, 01BH, 022H, 0E3H, 0C1H, 009H, 0E5H, 0CDH, 072H, 004H, 0E1H, 022H, 01BH DB 022H, 0EBH, 074H, 0D1H, 023H, 023H, 073H, 023H, 072H, 023H, 011H, 0A6H, 021H, 01AH, 077H, 023H DB 013H, 0B7H, 0C2H, 06DH, 005H, 0CDH, 0BEH, 005H, 023H, 0EBH, 062H, 06BH, 07EH, 023H, 0B6H, 0CAH DB 0FEH, 004H, 023H, 023H, 023H, 0AFH, 0BEH, 023H, 0C2H, 086H, 005H, 0EBH, 073H, 023H, 072H, 0C3H DB 07AH, 005H, 02AH, 0A3H, 021H, 044H, 04DH, 07EH, 023H, 0B6H, 02BH, 0C8H, 023H, 023H, 07EH, 023H DB 066H, 06FH, 0CDH, 06EH, 007H, 060H, 069H, 07EH, 023H, 066H, 06FH, 03FH, 0C8H, 03FH, 0D0H, 0C3H DB 095H, 005H, 0C0H, 02AH, 0A3H, 021H, 0AFH, 077H, 023H, 077H, 023H, 022H, 01BH, 022H, 02AH, 0A3H DB 021H, 02BH, 022H, 013H, 022H, 02AH, 0F4H, 021H, 022H, 008H, 022H, 0AFH, 0CDH, 00EH, 009H, 02AH DB 01BH, 022H, 022H, 01DH, 022H, 022H, 01FH, 022H, 0C1H, 02AH, 09FH, 021H, 0F9H, 021H, 0F8H, 021H DB 022H, 0F6H, 021H, 0AFH, 06FH, 067H, 022H, 019H, 022H, 032H, 010H, 022H, 022H, 023H, 022H, 0E5H DB 0C5H, 02AH, 013H, 022H, 0C9H, 03EH, 03FH, 0CDH, 07FH, 007H, 03EH, 020H, 0CDH, 07FH, 007H, 0C3H ;0600H DB 093H, 021H, 0AFH, 032H, 0F3H, 021H, 00EH, 005H, 011H, 0A6H, 021H, 07EH, 0FEH, 020H, 0CAH, 08AH DB 006H, 047H, 0FEH, 022H, 0CAH, 0AAH, 006H, 0B7H, 0CAH, 0B1H, 006H, 03AH, 0F3H, 021H, 0B7H, 07EH DB 0C2H, 08AH, 006H, 0FEH, 03FH, 03EH, 09EH, 0CAH, 08AH, 006H, 07EH, 0FEH, 030H, 0DAH, 035H, 006H DB 0FEH, 03CH, 0DAH, 08AH, 006H, 0D5H, 011H, 032H, 002H, 0C5H, 001H, 086H, 006H, 0C5H, 006H, 07FH DB 07EH, 0FEH, 061H, 0DAH, 04EH, 006H, 0FEH, 07BH, 0D2H, 04EH, 006H, 0E6H, 05FH, 077H, 04EH, 0EBH DB 023H, 0B6H, 0F2H, 050H, 006H, 004H, 07EH, 0E6H, 07FH, 0C8H, 0B9H, 0C2H, 050H, 006H, 0EBH, 0E5H DB 013H, 01AH, 0B7H, 0FAH, 082H, 006H, 04FH, 078H, 0FEH, 088H, 0C2H, 071H, 006H, 0CDH, 0FEH, 008H DB 02BH, 023H, 07EH, 0FEH, 061H, 0DAH, 07AH, 006H, 0E6H, 05FH, 0B9H, 0CAH, 060H, 006H, 0E1H, 0C3H DB 04EH, 006H, 048H, 0F1H, 0EBH, 0C9H, 0EBH, 079H, 0C1H, 0D1H, 023H, 012H, 013H, 00CH, 0D6H, 03AH DB 0CAH, 098H, 006H, 0FEH, 049H, 0C2H, 09BH, 006H, 032H, 0F3H, 021H, 0D6H, 054H, 0C2H, 00BH, 006H DB 047H, 07EH, 0B7H, 0CAH, 0B1H, 006H, 0B8H, 0CAH, 08AH, 006H, 023H, 012H, 00CH, 013H, 0C3H, 0A1H DB 006H, 021H, 0A5H, 021H, 012H, 013H, 012H, 013H, 012H, 0C9H, 03AH, 089H, 021H, 0B7H, 03EH, 000H DB 032H, 089H, 021H, 0C2H, 0CEH, 006H, 005H, 0CAH, 0EBH, 006H, 0CDH, 07FH, 007H, 03EH, 005H, 02BH DB 0CAH, 0E2H, 006H, 07EH, 0CDH, 07FH, 007H, 0C3H, 0F4H, 006H, 005H, 02BH, 0CDH, 07FH, 007H, 0C2H DB 0F4H, 006H, 0CDH, 07FH, 007H, 0CDH, 0A6H, 00BH, 0C3H, 0EBH, 006H, 021H, 0A6H, 021H, 006H, 001H DB 0AFH, 032H, 089H, 021H, 0CDH, 0A9H, 007H, 04FH, 0FEH, 07FH, 0CAH, 0BAH, 006H, 03AH, 089H, 021H ;0700H DB 0B7H, 0CAH, 00DH, 007H, 03EH, 000H, 0CDH, 07FH, 007H, 0AFH, 032H, 089H, 021H, 079H, 0FEH, 007H DB 0CAH, 051H, 007H, 0FEH, 003H, 0CCH, 0A6H, 00BH, 037H, 0C8H, 0FEH, 00DH, 0CAH, 0A1H, 00BH, 0FEH DB 015H, 0CAH, 0E5H, 006H, 0FEH, 040H, 0CAH, 0E2H, 006H, 0FEH, 05FH, 0CAH, 0DAH, 006H, 0FEH, 008H DB 0CAH, 0DAH, 006H, 0FEH, 012H, 0C2H, 04CH, 007H, 0C5H, 0D5H, 0E5H, 036H, 000H, 0CDH, 050H, 01DH DB 021H, 0A6H, 021H, 0CDH, 044H, 012H, 0E1H, 0D1H, 0C1H, 0C3H, 0F4H, 006H, 0FEH, 020H, 0DAH, 0F4H DB 006H, 078H, 0FEH, 049H, 03EH, 007H, 0D2H, 066H, 007H, 079H, 071H, 032H, 011H, 022H, 023H, 004H DB 0CDH, 07FH, 007H, 0C3H, 0F4H, 006H, 0CDH, 07FH, 007H, 03EH, 008H, 0C3H, 060H, 007H, 07CH, 092H DB 0C0H, 07DH, 093H, 0C9H, 07EH, 0E3H, 0BEH, 023H, 0E3H, 0CAH, 0FEH, 008H, 0C3H, 0A6H, 004H, 0F5H DB 03AH, 08AH, 021H, 0B7H, 0C2H, 079H, 012H, 0F1H, 0C5H, 0F5H, 0FEH, 020H, 0DAH, 0A3H, 007H, 03AH DB 087H, 021H, 047H, 03AH, 0F0H, 021H, 004H, 0CAH, 09FH, 007H, 005H, 0B8H, 0CCH, 0A6H, 00BH, 03CH DB 032H, 0F0H, 021H, 0F1H, 0C1H, 0CDH, 03BH, 01DH, 0C9H, 0CDH, 003H, 01CH, 0E6H, 07FH, 0FEH, 00FH DB 0C0H, 03AH, 08AH, 021H, 02FH, 032H, 08AH, 021H, 0AFH, 0C9H, 0CDH, 0CAH, 009H, 0C0H, 0C1H, 0CDH DB 092H, 005H, 0C5H, 0CDH, 010H, 008H, 0E1H, 04EH, 023H, 046H, 023H, 078H, 0B1H, 0CAH, 0F1H, 004H DB 0CDH, 019H, 008H, 0CDH, 029H, 009H, 0C5H, 0CDH, 0A6H, 00BH, 05EH, 023H, 056H, 023H, 0E5H, 0EBH DB 0CDH, 0E7H, 018H, 03EH, 020H, 0E1H, 0CDH, 07FH, 007H, 07EH, 0B7H, 023H, 0CAH, 0C6H, 007H, 0F2H DB 0E6H, 007H, 0D6H, 07FH, 04FH, 011H, 033H, 002H, 01AH, 013H, 0B7H, 0F2H, 0F8H, 007H, 00DH, 0C2H ;0800H DB 0F8H, 007H, 0E6H, 07FH, 0CDH, 07FH, 007H, 01AH, 013H, 0B7H, 0F2H, 002H, 008H, 0C3H, 0E9H, 007H DB 0E5H, 02AH, 08DH, 021H, 022H, 08BH, 021H, 0E1H, 0C9H, 0E5H, 0D5H, 02AH, 08BH, 021H, 011H, 0FFH DB 0FFH, 0EDH, 05AH, 022H, 08BH, 021H, 0D1H, 0E1H, 0F0H, 0E5H, 02AH, 08DH, 021H, 022H, 08BH, 021H DB 0CDH, 003H, 01CH, 0FEH, 003H, 0CAH, 03CH, 008H, 0E1H, 0C3H, 019H, 008H, 02AH, 08DH, 021H, 022H DB 08BH, 021H, 0C3H, 06DH, 001H, 03EH, 064H, 032H, 010H, 022H, 0CDH, 0ACH, 00AH, 0C1H, 0E5H, 0CDH DB 095H, 00AH, 022H, 00CH, 022H, 021H, 002H, 000H, 039H, 0CDH, 053H, 004H, 0D1H, 0C2H, 075H, 008H DB 009H, 0D5H, 02BH, 056H, 02BH, 05EH, 023H, 023H, 0E5H, 02AH, 00CH, 022H, 0CDH, 06EH, 007H, 0E1H DB 0C2H, 059H, 008H, 0D1H, 0F9H, 0EBH, 00EH, 008H, 0CDH, 083H, 004H, 0E5H, 02AH, 00CH, 022H, 0E3H DB 0E5H, 02AH, 0A1H, 021H, 0E3H, 0CDH, 06EH, 00DH, 0CDH, 074H, 007H, 0A6H, 0CDH, 06BH, 00DH, 0E5H DB 0CDH, 099H, 017H, 0E1H, 0C5H, 0D5H, 001H, 000H, 081H, 051H, 05AH, 07EH, 0FEH, 0ABH, 03EH, 001H DB 0C2H, 0B1H, 008H, 0CDH, 0FEH, 008H, 0CDH, 06BH, 00DH, 0E5H, 0CDH, 099H, 017H, 0CDH, 04DH, 017H DB 0E1H, 0C5H, 0D5H, 0F5H, 033H, 0E5H, 02AH, 013H, 022H, 0E3H, 006H, 081H, 0C5H, 033H, 0CDH, 029H DB 009H, 022H, 013H, 022H, 07EH, 0FEH, 03AH, 0CAH, 0DEH, 008H, 0B7H, 0C2H, 0A6H, 004H, 023H, 07EH DB 023H, 0B6H, 0CAH, 050H, 009H, 023H, 05EH, 023H, 056H, 0EBH, 022H, 0A1H, 021H, 0EBH, 0CDH, 0FEH DB 008H, 011H, 0BEH, 008H, 0D5H, 0C8H, 0D6H, 080H, 0DAH, 0ACH, 00AH, 0FEH, 025H, 0D2H, 0A6H, 004H DB 007H, 04FH, 006H, 000H, 0EBH, 021H, 04EH, 003H, 009H, 04EH, 023H, 046H, 0C5H, 0EBH, 023H, 07EH ;0900H DB 0FEH, 03AH, 0D0H, 0FEH, 020H, 0CAH, 0FEH, 008H, 0FEH, 030H, 03FH, 03CH, 03DH, 0C9H, 0EBH, 02AH DB 0A3H, 021H, 0CAH, 023H, 009H, 0EBH, 0CDH, 0CAH, 009H, 0E5H, 0CDH, 092H, 005H, 060H, 069H, 0D1H DB 0D2H, 06BH, 00AH, 02BH, 022H, 021H, 022H, 0EBH, 0C9H, 0DFH, 0C8H, 0D7H, 0FEH, 01BH, 028H, 011H DB 0FEH, 003H, 028H, 00DH, 0FEH, 013H, 0C0H, 0D7H, 0FEH, 011H, 0C8H, 0FEH, 003H, 028H, 007H, 018H DB 0F6H, 03EH, 0FFH, 032H, 092H, 021H, 0C0H, 0F6H, 0C0H, 022H, 013H, 022H, 021H, 0F6H, 0FFH, 0C1H DB 02AH, 0A1H, 021H, 0F5H, 07DH, 0A4H, 03CH, 0CAH, 063H, 009H, 022H, 017H, 022H, 02AH, 013H, 022H DB 022H, 019H, 022H, 0AFH, 032H, 08AH, 021H, 0CDH, 099H, 00BH, 0F1H, 021H, 049H, 004H, 0C2H, 0DAH DB 004H, 0C3H, 0F1H, 004H, 02AH, 019H, 022H, 07CH, 0B5H, 01EH, 020H, 0CAH, 0BAH, 004H, 0EBH, 02AH DB 017H, 022H, 022H, 0A1H, 021H, 0EBH, 0C9H, 0CDH, 0CCH, 014H, 0C0H, 032H, 086H, 021H, 0C9H, 0E5H DB 02AH, 08FH, 021H, 006H, 000H, 04FH, 009H, 022H, 08FH, 021H, 0E1H, 0C9H, 07EH, 0FEH, 041H, 0D8H DB 0FEH, 05BH, 03FH, 0C9H, 0CDH, 0FEH, 008H, 0CDH, 06BH, 00DH, 0CDH, 04DH, 017H, 0FAH, 0C5H, 009H DB 03AH, 02CH, 022H, 0FEH, 090H, 0DAH, 0F5H, 017H, 001H, 080H, 090H, 011H, 000H, 000H, 0E5H, 0CDH DB 0C8H, 017H, 0E1H, 051H, 0C8H, 01EH, 008H, 0C3H, 0BAH, 004H, 02BH, 011H, 000H, 000H, 0CDH, 0FEH DB 008H, 0D0H, 0E5H, 0F5H, 021H, 098H, 019H, 0CDH, 06EH, 007H, 0DAH, 0A6H, 004H, 062H, 06BH, 019H DB 029H, 019H, 029H, 0F1H, 0D6H, 030H, 05FH, 016H, 000H, 019H, 0EBH, 0E1H, 0C3H, 0CEH, 009H, 0CAH DB 0C2H, 005H, 0CDH, 0A7H, 009H, 02BH, 0CDH, 0FEH, 008H, 0E5H, 02AH, 0F4H, 021H, 0CAH, 012H, 00AH ;0A00H DB 0E1H, 0CDH, 074H, 007H, 02CH, 0D5H, 0CDH, 0A7H, 009H, 02BH, 0CDH, 0FEH, 008H, 0C2H, 0A6H, 004H DB 0E3H, 0EBH, 07DH, 093H, 05FH, 07CH, 09AH, 057H, 0DAH, 09BH, 004H, 0E5H, 02AH, 01BH, 022H, 001H DB 028H, 000H, 009H, 0CDH, 06EH, 007H, 0D2H, 09BH, 004H, 0EBH, 022H, 09FH, 021H, 0E1H, 022H, 0F4H DB 021H, 0E1H, 0C3H, 0C2H, 005H, 0CAH, 0BEH, 005H, 0CDH, 0C2H, 005H, 001H, 0BEH, 008H, 0C3H, 051H DB 00AH, 00EH, 003H, 0CDH, 083H, 004H, 0C1H, 0E5H, 0E5H, 02AH, 0A1H, 021H, 0E3H, 03EH, 08CH, 0F5H DB 033H, 0C5H, 0CDH, 0CAH, 009H, 0CDH, 097H, 00AH, 0E5H, 02AH, 0A1H, 021H, 0CDH, 06EH, 007H, 0E1H DB 023H, 0DCH, 095H, 005H, 0D4H, 092H, 005H, 060H, 069H, 02BH, 0D8H, 01EH, 00EH, 0C3H, 0BAH, 004H DB 0C0H, 016H, 0FFH, 0CDH, 04FH, 004H, 0F9H, 0FEH, 08CH, 01EH, 004H, 0C2H, 0BAH, 004H, 0E1H, 022H DB 0A1H, 021H, 023H, 07CH, 0B5H, 0C2H, 08FH, 00AH, 03AH, 011H, 022H, 0B7H, 0C2H, 0F0H, 004H, 021H DB 0BEH, 008H, 0E3H, 03EH, 0E1H, 001H, 03AH, 00EH, 000H, 006H, 000H, 079H, 048H, 047H, 07EH, 0B7H DB 0C8H, 0B8H, 0C8H, 023H, 0FEH, 022H, 0CAH, 09BH, 00AH, 0C3H, 09EH, 00AH, 0CDH, 061H, 00FH, 0CDH DB 074H, 007H, 0B4H, 0D5H, 03AH, 0F2H, 021H, 0F5H, 0CDH, 07DH, 00DH, 0F1H, 0E3H, 022H, 013H, 022H DB 01FH, 0CDH, 070H, 00DH, 0CAH, 0FFH, 00AH, 0E5H, 02AH, 029H, 022H, 0E5H, 023H, 023H, 05EH, 023H DB 056H, 02AH, 0A3H, 021H, 0CDH, 06EH, 007H, 0D2H, 0EEH, 00AH, 02AH, 09FH, 021H, 0CDH, 06EH, 007H DB 0D1H, 0D2H, 0F6H, 00AH, 021H, 004H, 022H, 0CDH, 06EH, 007H, 0D2H, 0F6H, 00AH, 03EH, 0D1H, 0CDH DB 0A5H, 013H, 0EBH, 0CDH, 0DEH, 011H, 0CDH, 0A5H, 013H, 0E1H, 0CDH, 0A8H, 017H, 0E1H, 0C9H, 0E5H ;0B00H DB 0CDH, 0A5H, 017H, 0D1H, 0E1H, 0C9H, 0CDH, 0CCH, 014H, 07EH, 047H, 0FEH, 08CH, 0CAH, 015H, 00BH DB 0CDH, 074H, 007H, 088H, 02BH, 04BH, 00DH, 078H, 0CAH, 0E6H, 008H, 0CDH, 0CBH, 009H, 0FEH, 02CH DB 0C0H, 0C3H, 016H, 00BH, 0CDH, 07DH, 00DH, 07EH, 0FEH, 088H, 0CAH, 032H, 00BH, 0CDH, 074H, 007H DB 0A9H, 02BH, 0CDH, 06EH, 00DH, 0CDH, 04DH, 017H, 0CAH, 097H, 00AH, 0CDH, 0FEH, 008H, 0DAH, 052H DB 00AH, 0C3H, 0E5H, 008H, 02BH, 0CDH, 0FEH, 008H, 0CAH, 0A6H, 00BH, 0C8H, 0FEH, 0A5H, 0CAH, 0D9H DB 00BH, 0FEH, 0A8H, 0CAH, 0D9H, 00BH, 0E5H, 0FEH, 02CH, 0CAH, 0C2H, 00BH, 0FEH, 03BH, 0CAH, 0FCH DB 00BH, 0C1H, 0CDH, 07DH, 00DH, 0E5H, 03AH, 0F2H, 021H, 0B7H, 0C2H, 092H, 00BH, 0CDH, 0F2H, 018H DB 0CDH, 002H, 012H, 036H, 020H, 02AH, 029H, 022H, 034H, 02AH, 029H, 022H, 03AH, 087H, 021H, 047H DB 004H, 0CAH, 08EH, 00BH, 004H, 03AH, 0F0H, 021H, 086H, 03DH, 0B8H, 0D4H, 0A6H, 00BH, 0CDH, 047H DB 012H, 0AFH, 0C4H, 047H, 012H, 0E1H, 0C3H, 044H, 00BH, 03AH, 0F0H, 021H, 0B7H, 0C8H, 0C3H, 0A6H DB 00BH, 036H, 000H, 021H, 0A5H, 021H, 03EH, 00DH, 0CDH, 07FH, 007H, 03EH, 00AH, 0CDH, 07FH, 007H DB 0AFH, 032H, 0F0H, 021H, 03AH, 086H, 021H, 03DH, 0C8H, 0F5H, 0AFH, 0CDH, 07FH, 007H, 0F1H, 0C3H DB 0B7H, 00BH, 03AH, 088H, 021H, 047H, 03AH, 0F0H, 021H, 0B8H, 0D4H, 0A6H, 00BH, 0D2H, 0FCH, 00BH DB 0D6H, 00EH, 0D2H, 0D0H, 00BH, 02FH, 0C3H, 0F1H, 00BH, 0F5H, 0CDH, 0C9H, 014H, 0CDH, 074H, 007H DB 029H, 02BH, 0F1H, 0D6H, 0A8H, 0E5H, 0CAH, 0ECH, 00BH, 03AH, 0F0H, 021H, 02FH, 083H, 0D2H, 0FCH DB 00BH, 03CH, 047H, 03EH, 020H, 0CDH, 07FH, 007H, 005H, 0C2H, 0F5H, 00BH, 0E1H, 0CDH, 0FEH, 008H ;0C00H DB 0C3H, 04BH, 00BH, 03FH, 052H, 065H, 064H, 06FH, 020H, 066H, 072H, 06FH, 06DH, 020H, 073H, 074H DB 061H, 072H, 074H, 00DH, 00AH, 000H, 03AH, 012H, 022H, 0B7H, 0C2H, 0A0H, 004H, 0C1H, 021H, 003H DB 00CH, 0CDH, 044H, 012H, 0C3H, 0F1H, 005H, 0CDH, 0AFH, 011H, 07EH, 0FEH, 022H, 03EH, 000H, 032H DB 08AH, 021H, 0C2H, 041H, 00CH, 0CDH, 003H, 012H, 0CDH, 074H, 007H, 03BH, 0E5H, 0CDH, 047H, 012H DB 03EH, 0E5H, 0CDH, 0F5H, 005H, 0C1H, 0DAH, 04DH, 009H, 023H, 07EH, 0B7H, 02BH, 0C5H, 0CAH, 094H DB 00AH, 036H, 02CH, 0C3H, 05BH, 00CH, 0E5H, 02AH, 021H, 022H, 0F6H, 0AFH, 032H, 012H, 022H, 0E3H DB 0C3H, 067H, 00CH, 0CDH, 074H, 007H, 02CH, 0CDH, 061H, 00FH, 0E3H, 0D5H, 07EH, 0FEH, 02CH, 0CAH DB 08FH, 00CH, 03AH, 012H, 022H, 0B7H, 0C2H, 0FCH, 00CH, 03EH, 03FH, 0CDH, 07FH, 007H, 0CDH, 0F5H DB 005H, 0D1H, 0C1H, 0DAH, 04DH, 009H, 023H, 07EH, 0B7H, 02BH, 0C5H, 0CAH, 094H, 00AH, 0D5H, 03AH DB 0F2H, 021H, 0B7H, 0CAH, 0B9H, 00CH, 0CDH, 0FEH, 008H, 057H, 047H, 0FEH, 022H, 0CAH, 0ADH, 00CH DB 03AH, 012H, 022H, 0B7H, 057H, 0CAH, 0AAH, 00CH, 016H, 03AH, 006H, 02CH, 02BH, 0CDH, 006H, 012H DB 0EBH, 021H, 0C4H, 00CH, 0E3H, 0D5H, 0C3H, 0C7H, 00AH, 0CDH, 0FEH, 008H, 0CDH, 054H, 018H, 0E3H DB 0CDH, 0A5H, 017H, 0E1H, 02BH, 0CDH, 0FEH, 008H, 0CAH, 0D0H, 00CH, 0FEH, 02CH, 0C2H, 016H, 00CH DB 0E3H, 02BH, 0CDH, 0FEH, 008H, 0C2H, 063H, 00CH, 0D1H, 03AH, 012H, 022H, 0B7H, 0EBH, 0C2H, 024H DB 009H, 0D5H, 0B6H, 021H, 0EBH, 00CH, 0C4H, 044H, 012H, 0E1H, 0C9H, 03FH, 045H, 078H, 074H, 072H DB 061H, 020H, 069H, 067H, 06EH, 06FH, 072H, 065H, 064H, 00DH, 00AH, 000H, 0CDH, 095H, 00AH, 0B7H ;0D00H DB 0C2H, 015H, 00DH, 023H, 07EH, 023H, 0B6H, 01EH, 006H, 0CAH, 0BAH, 004H, 023H, 05EH, 023H, 056H DB 0EBH, 022H, 00EH, 022H, 0EBH, 0CDH, 0FEH, 008H, 0FEH, 083H, 0C2H, 0FCH, 00CH, 0C3H, 08FH, 00CH DB 011H, 000H, 000H, 0C4H, 061H, 00FH, 022H, 013H, 022H, 0CDH, 04FH, 004H, 0C2H, 0ACH, 004H, 0F9H DB 0D5H, 07EH, 023H, 0F5H, 0D5H, 0CDH, 08BH, 017H, 0E3H, 0E5H, 0CDH, 0F8H, 014H, 0E1H, 0CDH, 0A5H DB 017H, 0E1H, 0CDH, 09CH, 017H, 0E5H, 0CDH, 0C8H, 017H, 0E1H, 0C1H, 090H, 0CDH, 09CH, 017H, 0CAH DB 05BH, 00DH, 0EBH, 022H, 0A1H, 021H, 069H, 060H, 0C3H, 0BAH, 008H, 0F9H, 02AH, 013H, 022H, 07EH DB 0FEH, 02CH, 0C2H, 0BEH, 008H, 0CDH, 0FEH, 008H, 0CDH, 023H, 00DH, 0CDH, 07DH, 00DH, 0F6H, 037H DB 03AH, 0F2H, 021H, 08FH, 0B7H, 0E8H, 0C3H, 0B8H, 004H, 0CDH, 074H, 007H, 028H, 02BH, 016H, 000H DB 0D5H, 00EH, 001H, 0CDH, 083H, 004H, 0CDH, 0F4H, 00DH, 022H, 015H, 022H, 02AH, 015H, 022H, 0C1H DB 078H, 0FEH, 078H, 0D4H, 06EH, 00DH, 07EH, 016H, 000H, 0D6H, 0B3H, 0DAH, 0B5H, 00DH, 0FEH, 003H DB 0D2H, 0B5H, 00DH, 0FEH, 001H, 017H, 0AAH, 0BAH, 057H, 0DAH, 0A6H, 004H, 022H, 00AH, 022H, 0CDH DB 0FEH, 008H, 0C3H, 099H, 00DH, 07AH, 0B7H, 0C2H, 0DCH, 00EH, 07EH, 022H, 00AH, 022H, 0D6H, 0ACH DB 0D8H, 0FEH, 007H, 0D0H, 05FH, 03AH, 0F2H, 021H, 03DH, 0B3H, 07BH, 0CAH, 03AH, 013H, 007H, 083H DB 05FH, 021H, 098H, 003H, 019H, 078H, 056H, 0BAH, 0D0H, 023H, 0CDH, 06EH, 00DH, 0C5H, 001H, 08CH DB 00DH, 0C5H, 043H, 04AH, 0CDH, 07EH, 017H, 058H, 051H, 04EH, 023H, 046H, 023H, 0C5H, 02AH, 00AH DB 022H, 0C3H, 080H, 00DH, 0AFH, 032H, 0F2H, 021H, 0CDH, 0FEH, 008H, 01EH, 024H, 0CAH, 0BAH, 004H ;0E00H DB 0DAH, 054H, 018H, 0CDH, 09CH, 009H, 0D2H, 05BH, 00EH, 0FEH, 026H, 020H, 012H, 0CDH, 0FEH, 008H DB 0FEH, 048H, 0CAH, 098H, 01CH, 0FEH, 042H, 0CAH, 008H, 01DH, 01EH, 002H, 0CAH, 0BAH, 004H, 0FEH DB 0ACH, 0CAH, 0F4H, 00DH, 0FEH, 02EH, 0CAH, 054H, 018H, 0FEH, 0ADH, 0CAH, 04AH, 00EH, 0FEH, 022H DB 0CAH, 003H, 012H, 0FEH, 0AAH, 0CAH, 03CH, 00FH, 0FEH, 0A7H, 0CAH, 067H, 011H, 0D6H, 0B6H, 0D2H DB 06CH, 00EH, 0CDH, 079H, 00DH, 0CDH, 074H, 007H, 029H, 0C9H, 016H, 07DH, 0CDH, 080H, 00DH, 02AH DB 015H, 022H, 0E5H, 0CDH, 076H, 017H, 0CDH, 06EH, 00DH, 0E1H, 0C9H, 0CDH, 061H, 00FH, 0E5H, 0EBH DB 022H, 029H, 022H, 03AH, 0F2H, 021H, 0B7H, 0CCH, 08BH, 017H, 0E1H, 0C9H, 006H, 000H, 007H, 04FH DB 0C5H, 0CDH, 0FEH, 008H, 079H, 0FEH, 031H, 0DAH, 093H, 00EH, 0CDH, 079H, 00DH, 0CDH, 074H, 007H DB 02CH, 0CDH, 06FH, 00DH, 0EBH, 02AH, 029H, 022H, 0E3H, 0E5H, 0EBH, 0CDH, 0CCH, 014H, 0EBH, 0E3H DB 0C3H, 09BH, 00EH, 0CDH, 042H, 00EH, 0E3H, 011H, 056H, 00EH, 0D5H, 001H, 0FBH, 001H, 009H, 04EH DB 023H, 066H, 069H, 0E9H, 015H, 0FEH, 0ADH, 0C8H, 0FEH, 02DH, 0C8H, 014H, 0FEH, 02BH, 0C8H, 0FEH DB 0ACH, 0C8H, 02BH, 0C9H, 0F6H, 0AFH, 0F5H, 0CDH, 06EH, 00DH, 0CDH, 0B0H, 009H, 0F1H, 0EBH, 0C1H DB 0E3H, 0EBH, 0CDH, 08EH, 017H, 0F5H, 0CDH, 0B0H, 009H, 0F1H, 0C1H, 079H, 021H, 025H, 011H, 0C2H DB 0D7H, 00EH, 0A3H, 04FH, 078H, 0A2H, 0E9H, 0B3H, 04FH, 078H, 0B2H, 0E9H, 021H, 0EEH, 00EH, 03AH DB 0F2H, 021H, 01FH, 07AH, 017H, 05FH, 016H, 064H, 078H, 0BAH, 0D0H, 0C3H, 0DDH, 00DH, 0F0H, 00EH DB 079H, 0B7H, 01FH, 0C1H, 0D1H, 0F5H, 0CDH, 070H, 00DH, 021H, 032H, 00FH, 0E5H, 0CAH, 0C8H, 017H ;0F00H DB 0AFH, 032H, 0F2H, 021H, 0D5H, 0CDH, 087H, 013H, 07EH, 023H, 023H, 04EH, 023H, 046H, 0D1H, 0C5H DB 0F5H, 0CDH, 08BH, 013H, 0CDH, 09CH, 017H, 0F1H, 057H, 0E1H, 07BH, 0B2H, 0C8H, 07AH, 0D6H, 001H DB 0D8H, 0AFH, 0BBH, 03CH, 0D0H, 015H, 01DH, 00AH, 0BEH, 023H, 003H, 0CAH, 01AH, 00FH, 03FH, 0C3H DB 058H, 017H, 03CH, 08FH, 0C1H, 0A0H, 0C6H, 0FFH, 09FH, 0C3H, 05FH, 017H, 016H, 05AH, 0CDH, 080H DB 00DH, 0CDH, 06EH, 00DH, 0CDH, 0B0H, 009H, 07BH, 02FH, 04FH, 07AH, 02FH, 0CDH, 025H, 011H, 0C1H DB 0C3H, 08CH, 00DH, 02BH, 0CDH, 0FEH, 008H, 0C8H, 0CDH, 074H, 007H, 02CH, 001H, 053H, 00FH, 0C5H DB 0F6H, 0AFH, 032H, 0F1H, 021H, 046H, 0CDH, 09CH, 009H, 0DAH, 0A6H, 004H, 0AFH, 04FH, 032H, 0F2H DB 021H, 0CDH, 0FEH, 008H, 0DAH, 07DH, 00FH, 0CDH, 09CH, 009H, 0DAH, 08AH, 00FH, 04FH, 0CDH, 0FEH DB 008H, 0DAH, 07EH, 00FH, 0CDH, 09CH, 009H, 0D2H, 07EH, 00FH, 0D6H, 024H, 0C2H, 099H, 00FH, 03CH DB 032H, 0F2H, 021H, 00FH, 081H, 04FH, 0CDH, 0FEH, 008H, 03AH, 010H, 022H, 03DH, 0CAH, 046H, 010H DB 0F2H, 0A9H, 00FH, 07EH, 0D6H, 028H, 0CAH, 01EH, 010H, 0AFH, 032H, 010H, 022H, 0E5H, 050H, 059H DB 02AH, 023H, 022H, 0CDH, 06EH, 007H, 011H, 025H, 022H, 0CAH, 08EH, 016H, 02AH, 01DH, 022H, 0EBH DB 02AH, 01BH, 022H, 0CDH, 06EH, 007H, 0CAH, 0DCH, 00FH, 079H, 096H, 023H, 0C2H, 0D1H, 00FH, 078H DB 096H, 023H, 0CAH, 010H, 010H, 023H, 023H, 023H, 023H, 0C3H, 0C3H, 00FH, 0E1H, 0E3H, 0D5H, 011H DB 05EH, 00EH, 0CDH, 06EH, 007H, 0D1H, 0CAH, 013H, 010H, 0E3H, 0E5H, 0C5H, 001H, 006H, 000H, 02AH DB 01FH, 022H, 0E5H, 009H, 0C1H, 0E5H, 0CDH, 072H, 004H, 0E1H, 022H, 01FH, 022H, 060H, 069H, 022H ;1000H DB 01DH, 022H, 02BH, 036H, 000H, 0CDH, 06EH, 007H, 0C2H, 002H, 010H, 0D1H, 073H, 023H, 072H, 023H DB 0EBH, 0E1H, 0C9H, 032H, 02CH, 022H, 021H, 042H, 004H, 022H, 029H, 022H, 0E1H, 0C9H, 0E5H, 02AH DB 0F1H, 021H, 0E3H, 057H, 0D5H, 0C5H, 0CDH, 0A4H, 009H, 0C1H, 0F1H, 0EBH, 0E3H, 0E5H, 0EBH, 03CH DB 057H, 07EH, 0FEH, 02CH, 0CAH, 024H, 010H, 0CDH, 074H, 007H, 029H, 022H, 015H, 022H, 0E1H, 022H DB 0F1H, 021H, 01EH, 000H, 0D5H, 011H, 0E5H, 0F5H, 02AH, 01DH, 022H, 03EH, 019H, 0EBH, 02AH, 01FH DB 022H, 0EBH, 0CDH, 06EH, 007H, 0CAH, 07EH, 010H, 07EH, 0B9H, 023H, 0C2H, 060H, 010H, 07EH, 0B8H DB 023H, 05EH, 023H, 056H, 023H, 0C2H, 04CH, 010H, 03AH, 0F1H, 021H, 0B7H, 0C2H, 0AFH, 004H, 0F1H DB 044H, 04DH, 0CAH, 08EH, 016H, 096H, 0CAH, 0DCH, 010H, 01EH, 010H, 0C3H, 0BAH, 004H, 011H, 004H DB 000H, 0F1H, 0CAH, 0C5H, 009H, 071H, 023H, 070H, 023H, 04FH, 0CDH, 083H, 004H, 023H, 023H, 022H DB 00AH, 022H, 071H, 023H, 03AH, 0F1H, 021H, 017H, 079H, 001H, 00BH, 000H, 0D2H, 0A1H, 010H, 0C1H DB 003H, 071H, 023H, 070H, 023H, 0F5H, 0E5H, 0CDH, 039H, 018H, 0EBH, 0E1H, 0F1H, 03DH, 0C2H, 099H DB 010H, 0F5H, 042H, 04BH, 0EBH, 019H, 0DAH, 09BH, 004H, 0CDH, 08CH, 004H, 022H, 01FH, 022H, 02BH DB 036H, 000H, 0CDH, 06EH, 007H, 0C2H, 0BFH, 010H, 003H, 057H, 02AH, 00AH, 022H, 05EH, 0EBH, 029H DB 009H, 0EBH, 02BH, 02BH, 073H, 023H, 072H, 023H, 0F1H, 0DAH, 000H, 011H, 047H, 04FH, 07EH, 023H DB 016H, 0E1H, 05EH, 023H, 056H, 023H, 0E3H, 0F5H, 0CDH, 06EH, 007H, 0D2H, 079H, 010H, 0E5H, 0CDH DB 039H, 018H, 0D1H, 019H, 0F1H, 03DH, 044H, 04DH, 0C2H, 0E1H, 010H, 029H, 029H, 0C1H, 009H, 0EBH ;1100H DB 02AH, 015H, 022H, 0C9H, 02AH, 01FH, 022H, 0EBH, 021H, 000H, 000H, 039H, 03AH, 0F2H, 021H, 0B7H DB 0CAH, 020H, 011H, 0CDH, 087H, 013H, 0CDH, 087H, 012H, 02AH, 09FH, 021H, 0EBH, 02AH, 008H, 022H DB 07DH, 093H, 04FH, 07CH, 09AH, 041H, 050H, 01EH, 000H, 021H, 0F2H, 021H, 073H, 006H, 090H, 0C3H DB 064H, 017H, 03AH, 0F0H, 021H, 047H, 0AFH, 0C3H, 026H, 011H, 0CDH, 0BDH, 011H, 0CDH, 0AFH, 011H DB 001H, 095H, 00AH, 0C5H, 0D5H, 0CDH, 074H, 007H, 028H, 0CDH, 061H, 00FH, 0E5H, 0EBH, 02BH, 056H DB 02BH, 05EH, 0E1H, 0CDH, 06EH, 00DH, 0CDH, 074H, 007H, 029H, 0CDH, 074H, 007H, 0B4H, 044H, 04DH DB 0E3H, 071H, 023H, 070H, 0C3H, 0FCH, 011H, 0CDH, 0BDH, 011H, 0D5H, 0CDH, 042H, 00EH, 0CDH, 06EH DB 00DH, 0E3H, 05EH, 023H, 056H, 023H, 07AH, 0B3H, 0CAH, 0B2H, 004H, 07EH, 023H, 066H, 06FH, 0E5H DB 02AH, 023H, 022H, 0E3H, 022H, 023H, 022H, 02AH, 027H, 022H, 0E5H, 02AH, 025H, 022H, 0E5H, 021H DB 025H, 022H, 0D5H, 0CDH, 0A5H, 017H, 0E1H, 0CDH, 06BH, 00DH, 02BH, 0CDH, 0FEH, 008H, 0C2H, 0A6H DB 004H, 0E1H, 022H, 025H, 022H, 0E1H, 022H, 027H, 022H, 0E1H, 022H, 023H, 022H, 0E1H, 0C9H, 0E5H DB 02AH, 0A1H, 021H, 023H, 07CH, 0B5H, 0E1H, 0C0H, 01EH, 016H, 0C3H, 0BAH, 004H, 0CDH, 074H, 007H DB 0A7H, 03EH, 080H, 032H, 010H, 022H, 0B6H, 047H, 0CDH, 066H, 00FH, 0C3H, 06EH, 00DH, 0CDH, 06EH DB 00DH, 0CDH, 0F2H, 018H, 0CDH, 002H, 012H, 0CDH, 087H, 013H, 001H, 0E2H, 013H, 0C5H, 07EH, 023H DB 023H, 0E5H, 0CDH, 05DH, 012H, 0E1H, 04EH, 023H, 046H, 0CDH, 0F6H, 011H, 0E5H, 06FH, 0CDH, 07AH DB 013H, 0D1H, 0C9H, 0CDH, 05DH, 012H, 021H, 004H, 022H, 0E5H, 077H, 023H, 023H, 073H, 023H, 072H ;1200H DB 0E1H, 0C9H, 02BH, 006H, 022H, 050H, 0E5H, 00EH, 0FFH, 023H, 07EH, 00CH, 0B7H, 0CAH, 018H, 012H DB 0BAH, 0CAH, 018H, 012H, 0B8H, 0C2H, 009H, 012H, 0FEH, 022H, 0CCH, 0FEH, 008H, 0E3H, 023H, 0EBH DB 079H, 0CDH, 0F6H, 011H, 011H, 004H, 022H, 02AH, 0F6H, 021H, 022H, 029H, 022H, 03EH, 001H, 032H DB 0F2H, 021H, 0CDH, 0A8H, 017H, 0CDH, 06EH, 007H, 022H, 0F6H, 021H, 0E1H, 07EH, 0C0H, 01EH, 01EH DB 0C3H, 0BAH, 004H, 023H, 0CDH, 002H, 012H, 0CDH, 087H, 013H, 0CDH, 09CH, 017H, 01CH, 01DH, 0C8H DB 00AH, 0CDH, 07FH, 007H, 0FEH, 00DH, 0CCH, 0B0H, 00BH, 003H, 0C3H, 04EH, 012H, 0B7H, 00EH, 0F1H DB 0F5H, 02AH, 09FH, 021H, 0EBH, 02AH, 008H, 022H, 02FH, 04FH, 006H, 0FFH, 009H, 023H, 0CDH, 06EH DB 007H, 0DAH, 07BH, 012H, 022H, 008H, 022H, 023H, 0EBH, 0F1H, 0C9H, 0F1H, 01EH, 01AH, 0CAH, 0BAH DB 004H, 0BFH, 0F5H, 001H, 05FH, 012H, 0C5H, 02AH, 0F4H, 021H, 022H, 008H, 022H, 021H, 000H, 000H DB 0E5H, 02AH, 09FH, 021H, 0E5H, 021H, 0F8H, 021H, 0EBH, 02AH, 0F6H, 021H, 0EBH, 0CDH, 06EH, 007H DB 001H, 098H, 012H, 0C2H, 0ECH, 012H, 02AH, 01BH, 022H, 0EBH, 02AH, 01DH, 022H, 0EBH, 0CDH, 06EH DB 007H, 0CAH, 0BFH, 012H, 07EH, 023H, 023H, 0B7H, 0CDH, 0EFH, 012H, 0C3H, 0A9H, 012H, 0C1H, 0EBH DB 02AH, 01FH, 022H, 0EBH, 0CDH, 06EH, 007H, 0CAH, 015H, 013H, 0CDH, 09CH, 017H, 07BH, 0E5H, 009H DB 0B7H, 0F2H, 0BEH, 012H, 022H, 00AH, 022H, 0E1H, 04EH, 006H, 000H, 009H, 009H, 023H, 0EBH, 02AH DB 00AH, 022H, 0EBH, 0CDH, 06EH, 007H, 0CAH, 0BFH, 012H, 001H, 0DEH, 012H, 0C5H, 0F6H, 080H, 07EH DB 023H, 023H, 05EH, 023H, 056H, 023H, 0F0H, 0B7H, 0C8H, 044H, 04DH, 02AH, 008H, 022H, 0CDH, 06EH ;1300H DB 007H, 060H, 069H, 0D8H, 0E1H, 0E3H, 0CDH, 06EH, 007H, 0E3H, 0E5H, 060H, 069H, 0D0H, 0C1H, 0F1H DB 0F1H, 0E5H, 0D5H, 0C5H, 0C9H, 0D1H, 0E1H, 07DH, 0B4H, 0C8H, 02BH, 046H, 02BH, 04EH, 0E5H, 02BH DB 02BH, 06EH, 026H, 000H, 009H, 050H, 059H, 02BH, 044H, 04DH, 02AH, 008H, 022H, 0CDH, 075H, 004H DB 0E1H, 071H, 023H, 070H, 069H, 060H, 02BH, 0C3H, 08AH, 012H, 0C5H, 0E5H, 02AH, 029H, 022H, 0E3H DB 0CDH, 0F4H, 00DH, 0E3H, 0CDH, 06FH, 00DH, 07EH, 0E5H, 02AH, 029H, 022H, 0E5H, 086H, 01EH, 01CH DB 0DAH, 0BAH, 004H, 0CDH, 0F3H, 011H, 0D1H, 0CDH, 08BH, 013H, 0E3H, 0CDH, 08AH, 013H, 0E5H, 02AH DB 006H, 022H, 0EBH, 0CDH, 071H, 013H, 0CDH, 071H, 013H, 021H, 089H, 00DH, 0E3H, 0E5H, 0C3H, 024H DB 012H, 0E1H, 0E3H, 07EH, 023H, 023H, 04EH, 023H, 046H, 06FH, 02CH, 02DH, 0C8H, 00AH, 012H, 003H DB 013H, 0C3H, 07BH, 013H, 0CDH, 06FH, 00DH, 02AH, 029H, 022H, 0EBH, 0CDH, 0A5H, 013H, 0EBH, 0C0H DB 0D5H, 050H, 059H, 01BH, 04EH, 02AH, 008H, 022H, 0CDH, 06EH, 007H, 0C2H, 0A3H, 013H, 047H, 009H DB 022H, 008H, 022H, 0E1H, 0C9H, 02AH, 0F6H, 021H, 02BH, 046H, 02BH, 04EH, 02BH, 02BH, 0CDH, 06EH DB 007H, 0C0H, 022H, 0F6H, 021H, 0C9H, 001H, 035H, 011H, 0C5H, 0CDH, 084H, 013H, 0AFH, 057H, 032H DB 0F2H, 021H, 07EH, 0B7H, 0C9H, 001H, 035H, 011H, 0C5H, 0CDH, 0BAH, 013H, 0CAH, 0C5H, 009H, 023H DB 023H, 05EH, 023H, 056H, 01AH, 0C9H, 03EH, 001H, 0CDH, 0F3H, 011H, 0CDH, 0CFH, 014H, 02AH, 006H DB 022H, 073H, 0C1H, 0C3H, 024H, 012H, 0CDH, 07FH, 014H, 0AFH, 0E3H, 04FH, 0E5H, 07EH, 0B8H, 0DAH DB 0F4H, 013H, 078H, 011H, 00EH, 000H, 0C5H, 0CDH, 05DH, 012H, 0C1H, 0E1H, 0E5H, 023H, 023H, 046H ;1400H DB 023H, 066H, 068H, 006H, 000H, 009H, 044H, 04DH, 0CDH, 0F6H, 011H, 06FH, 0CDH, 07AH, 013H, 0D1H DB 0CDH, 08BH, 013H, 0C3H, 024H, 012H, 0CDH, 07FH, 014H, 0D1H, 0D5H, 01AH, 090H, 0C3H, 0EAH, 013H DB 0EBH, 07EH, 0CDH, 084H, 014H, 004H, 005H, 0CAH, 0C5H, 009H, 0C5H, 01EH, 0FFH, 0FEH, 029H, 0CAH DB 039H, 014H, 0CDH, 074H, 007H, 02CH, 0CDH, 0CCH, 014H, 0CDH, 074H, 007H, 029H, 0F1H, 0E3H, 001H DB 0ECH, 013H, 0C5H, 03DH, 0BEH, 006H, 000H, 0D0H, 04FH, 07EH, 091H, 0BBH, 047H, 0D8H, 043H, 0C9H DB 0CDH, 0BAH, 013H, 0CAH, 06DH, 015H, 05FH, 023H, 023H, 07EH, 023H, 066H, 06FH, 0E5H, 019H, 046H DB 072H, 0E3H, 0C5H, 07EH, 0FEH, 024H, 0C2H, 06EH, 014H, 0CDH, 098H, 01CH, 018H, 00DH, 0FEH, 025H DB 0C2H, 078H, 014H, 0CDH, 008H, 01DH, 018H, 003H, 0CDH, 054H, 018H, 0C1H, 0E1H, 070H, 0C9H, 0EBH DB 0CDH, 074H, 007H, 029H, 0C1H, 0D1H, 0C5H, 043H, 0C9H, 0CDH, 0CFH, 014H, 032H, 084H, 021H, 0CDH DB 083H, 021H, 0C3H, 035H, 011H, 0CDH, 0B9H, 014H, 0C3H, 04BH, 021H, 0CDH, 0B9H, 014H, 0F5H, 01EH DB 000H, 02BH, 0CDH, 0FEH, 008H, 0CAH, 0AFH, 014H, 0CDH, 074H, 007H, 02CH, 0CDH, 0CCH, 014H, 0C1H DB 0CDH, 083H, 021H, 0ABH, 0A0H, 0CAH, 0B0H, 014H, 0C9H, 0CDH, 0CCH, 014H, 032H, 084H, 021H, 032H DB 04CH, 021H, 0CDH, 074H, 007H, 02CH, 0C3H, 0CCH, 014H, 0CDH, 0FEH, 008H, 0CDH, 06BH, 00DH, 0CDH DB 0AAH, 009H, 07AH, 0B7H, 0C2H, 0C5H, 009H, 02BH, 0CDH, 0FEH, 008H, 07BH, 0C9H, 0CDH, 0B0H, 009H DB 01AH, 0C3H, 035H, 011H, 0CDH, 06BH, 00DH, 0CDH, 0B0H, 009H, 0D5H, 0CDH, 074H, 007H, 02CH, 0CDH DB 0CCH, 014H, 0D1H, 012H, 0C9H, 021H, 0CBH, 019H, 0CDH, 09CH, 017H, 0C3H, 007H, 015H, 0CDH, 09CH ;1500H DB 017H, 021H, 0C1H, 0D1H, 0CDH, 076H, 017H, 078H, 0B7H, 0C8H, 03AH, 02CH, 022H, 0B7H, 0CAH, 08EH DB 017H, 090H, 0D2H, 021H, 015H, 02FH, 03CH, 0EBH, 0CDH, 07EH, 017H, 0EBH, 0CDH, 08EH, 017H, 0C1H DB 0D1H, 0FEH, 019H, 0D0H, 0F5H, 0CDH, 0B3H, 017H, 067H, 0F1H, 0CDH, 0CCH, 015H, 0B4H, 021H, 029H DB 022H, 0F2H, 047H, 015H, 0CDH, 0ACH, 015H, 0D2H, 08DH, 015H, 023H, 034H, 0CAH, 0B5H, 004H, 02EH DB 001H, 0CDH, 0E2H, 015H, 0C3H, 08DH, 015H, 0AFH, 090H, 047H, 07EH, 09BH, 05FH, 023H, 07EH, 09AH DB 057H, 023H, 07EH, 099H, 04FH, 0DCH, 0B8H, 015H, 068H, 063H, 0AFH, 047H, 079H, 0B7H, 0C2H, 07AH DB 015H, 04AH, 054H, 065H, 06FH, 078H, 0D6H, 008H, 0FEH, 0E0H, 0C2H, 05BH, 015H, 0AFH, 032H, 02CH DB 022H, 0C9H, 005H, 029H, 07AH, 017H, 057H, 079H, 08FH, 04FH, 0F2H, 072H, 015H, 078H, 05CH, 045H DB 0B7H, 0CAH, 08DH, 015H, 021H, 02CH, 022H, 086H, 077H, 0D2H, 06DH, 015H, 0C8H, 078H, 021H, 02CH DB 022H, 0B7H, 0FCH, 09FH, 015H, 046H, 023H, 07EH, 0E6H, 080H, 0A9H, 04FH, 0C3H, 08EH, 017H, 01CH DB 0C0H, 014H, 0C0H, 00CH, 0C0H, 00EH, 080H, 034H, 0C0H, 0C3H, 0B5H, 004H, 07EH, 083H, 05FH, 023H DB 07EH, 08AH, 057H, 023H, 07EH, 089H, 04FH, 0C9H, 021H, 02DH, 022H, 07EH, 02FH, 077H, 0AFH, 06FH DB 090H, 047H, 07DH, 09BH, 05FH, 07DH, 09AH, 057H, 07DH, 099H, 04FH, 0C9H, 006H, 000H, 0D6H, 008H DB 0DAH, 0DBH, 015H, 043H, 05AH, 051H, 00EH, 000H, 0C3H, 0CEH, 015H, 0C6H, 009H, 06FH, 0AFH, 02DH DB 0C8H, 079H, 01FH, 04FH, 07AH, 01FH, 057H, 07BH, 01FH, 05FH, 078H, 01FH, 047H, 0C3H, 0DEH, 015H DB 000H, 000H, 000H, 081H, 003H, 0AAH, 056H, 019H, 080H, 0F1H, 022H, 076H, 080H, 045H, 0AAH, 038H ;1600H DB 082H, 0CDH, 04DH, 017H, 0B7H, 0EAH, 0C5H, 009H, 021H, 02CH, 022H, 07EH, 001H, 035H, 080H, 011H DB 0F3H, 004H, 090H, 0F5H, 070H, 0D5H, 0C5H, 0CDH, 007H, 015H, 0C1H, 0D1H, 004H, 0CDH, 0A3H, 016H DB 021H, 0F0H, 015H, 0CDH, 0FEH, 014H, 021H, 0F4H, 015H, 0CDH, 095H, 01AH, 001H, 080H, 080H, 011H DB 000H, 000H, 0CDH, 007H, 015H, 0F1H, 0CDH, 0C8H, 018H, 001H, 031H, 080H, 011H, 018H, 072H, 021H DB 0C1H, 0D1H, 0CDH, 04DH, 017H, 0C8H, 02EH, 000H, 0CDH, 00BH, 017H, 079H, 032H, 03BH, 022H, 0EBH DB 022H, 03CH, 022H, 001H, 000H, 000H, 050H, 058H, 021H, 058H, 015H, 0E5H, 021H, 064H, 016H, 0E5H DB 0E5H, 021H, 029H, 022H, 07EH, 023H, 0B7H, 0CAH, 090H, 016H, 0E5H, 02EH, 008H, 01FH, 067H, 079H DB 0D2H, 07EH, 016H, 0E5H, 02AH, 03CH, 022H, 019H, 0EBH, 0E1H, 03AH, 03BH, 022H, 089H, 01FH, 04FH DB 07AH, 01FH, 057H, 07BH, 01FH, 05FH, 078H, 01FH, 047H, 02DH, 07CH, 0C2H, 06DH, 016H, 0E1H, 0C9H DB 043H, 05AH, 051H, 04FH, 0C9H, 0CDH, 07EH, 017H, 001H, 020H, 084H, 011H, 000H, 000H, 0CDH, 08EH DB 017H, 0C1H, 0D1H, 0CDH, 04DH, 017H, 0CAH, 0A9H, 004H, 02EH, 0FFH, 0CDH, 00BH, 017H, 034H, 034H DB 02BH, 07EH, 032H, 057H, 021H, 02BH, 07EH, 032H, 053H, 021H, 02BH, 07EH, 032H, 04FH, 021H, 041H DB 0EBH, 0AFH, 04FH, 057H, 05FH, 032H, 05AH, 021H, 0E5H, 0C5H, 07DH, 0CDH, 04EH, 021H, 0DEH, 000H DB 03FH, 0D2H, 0DBH, 016H, 032H, 05AH, 021H, 0F1H, 0F1H, 037H, 0D2H, 0C1H, 0E1H, 079H, 03CH, 03DH DB 01FH, 0FAH, 08EH, 015H, 017H, 07BH, 017H, 05FH, 07AH, 017H, 057H, 079H, 017H, 04FH, 029H, 078H DB 017H, 047H, 03AH, 05AH, 021H, 017H, 032H, 05AH, 021H, 079H, 0B2H, 0B3H, 0C2H, 0C8H, 016H, 0E5H ;1700H DB 021H, 02CH, 022H, 035H, 0E1H, 0C2H, 0C8H, 016H, 0C3H, 0B5H, 004H, 078H, 0B7H, 0CAH, 02FH, 017H DB 07DH, 021H, 02CH, 022H, 0AEH, 080H, 047H, 01FH, 0A8H, 078H, 0F2H, 02EH, 017H, 0C6H, 080H, 077H DB 0CAH, 08EH, 016H, 0CDH, 0B3H, 017H, 077H, 02BH, 0C9H, 0CDH, 04DH, 017H, 02FH, 0E1H, 0B7H, 0E1H DB 0F2H, 06DH, 015H, 0C3H, 0B5H, 004H, 0CDH, 099H, 017H, 078H, 0B7H, 0C8H, 0C6H, 002H, 0DAH, 0B5H DB 004H, 047H, 0CDH, 007H, 015H, 021H, 02CH, 022H, 034H, 0C0H, 0C3H, 0B5H, 004H, 03AH, 02CH, 022H DB 0B7H, 0C8H, 03AH, 02BH, 022H, 0FEH, 02FH, 017H, 09FH, 0C0H, 03CH, 0C9H, 0CDH, 04DH, 017H, 006H DB 088H, 011H, 000H, 000H, 021H, 02CH, 022H, 04FH, 070H, 006H, 000H, 023H, 036H, 080H, 017H, 0C3H DB 055H, 015H, 0CDH, 04DH, 017H, 0F0H, 021H, 02BH, 022H, 07EH, 0EEH, 080H, 077H, 0C9H, 0EBH, 02AH DB 029H, 022H, 0E3H, 0E5H, 02AH, 02BH, 022H, 0E3H, 0E5H, 0EBH, 0C9H, 0CDH, 09CH, 017H, 0EBH, 022H DB 029H, 022H, 060H, 069H, 022H, 02BH, 022H, 0EBH, 0C9H, 021H, 029H, 022H, 05EH, 023H, 056H, 023H DB 04EH, 023H, 046H, 023H, 0C9H, 011H, 029H, 022H, 006H, 004H, 01AH, 077H, 013H, 023H, 005H, 0C2H DB 0AAH, 017H, 0C9H, 021H, 02BH, 022H, 07EH, 007H, 037H, 01FH, 077H, 03FH, 01FH, 023H, 023H, 077H DB 079H, 007H, 037H, 01FH, 04FH, 01FH, 0AEH, 0C9H, 078H, 0B7H, 0CAH, 04DH, 017H, 021H, 056H, 017H DB 0E5H, 0CDH, 04DH, 017H, 079H, 0C8H, 021H, 02BH, 022H, 0AEH, 079H, 0F8H, 0CDH, 0E2H, 017H, 01FH DB 0A9H, 0C9H, 023H, 078H, 0BEH, 0C0H, 02BH, 079H, 0BEH, 0C0H, 02BH, 07AH, 0BEH, 0C0H, 02BH, 07BH DB 096H, 0C0H, 0E1H, 0E1H, 0C9H, 047H, 04FH, 057H, 05FH, 0B7H, 0C8H, 0E5H, 0CDH, 099H, 017H, 0CDH ;1800H DB 0B3H, 017H, 0AEH, 067H, 0FCH, 019H, 018H, 03EH, 098H, 090H, 0CDH, 0CCH, 015H, 07CH, 017H, 0DCH DB 09FH, 015H, 006H, 000H, 0DCH, 0B8H, 015H, 0E1H, 0C9H, 01BH, 07AH, 0A3H, 03CH, 0C0H, 00BH, 0C9H DB 021H, 02CH, 022H, 07EH, 0FEH, 098H, 03AH, 029H, 022H, 0D0H, 07EH, 0CDH, 0F5H, 017H, 036H, 098H DB 07BH, 0F5H, 079H, 017H, 0CDH, 055H, 015H, 0F1H, 0C9H, 021H, 000H, 000H, 078H, 0B1H, 0C8H, 03EH DB 010H, 029H, 0DAH, 079H, 010H, 0EBH, 029H, 0EBH, 0D2H, 04FH, 018H, 009H, 0DAH, 079H, 010H, 03DH DB 0C2H, 041H, 018H, 0C9H, 0FEH, 02DH, 0F5H, 0CAH, 060H, 018H, 0FEH, 02BH, 0CAH, 060H, 018H, 02BH DB 0CDH, 06DH, 015H, 047H, 057H, 05FH, 02FH, 04FH, 0CDH, 0FEH, 008H, 0DAH, 0B1H, 018H, 0FEH, 02EH DB 0CAH, 08CH, 018H, 0FEH, 045H, 0C2H, 090H, 018H, 0CDH, 0FEH, 008H, 0CDH, 0A4H, 00EH, 0CDH, 0FEH DB 008H, 0DAH, 0D3H, 018H, 014H, 0C2H, 090H, 018H, 0AFH, 093H, 05FH, 00CH, 00CH, 0CAH, 068H, 018H DB 0E5H, 07BH, 090H, 0F4H, 0A9H, 018H, 0F2H, 09FH, 018H, 0F5H, 0CDH, 095H, 016H, 0F1H, 03CH, 0C2H DB 093H, 018H, 0D1H, 0F1H, 0CCH, 076H, 017H, 0EBH, 0C9H, 0C8H, 0F5H, 0CDH, 036H, 017H, 0F1H, 03DH DB 0C9H, 0D5H, 057H, 078H, 089H, 047H, 0C5H, 0E5H, 0D5H, 0CDH, 036H, 017H, 0F1H, 0D6H, 030H, 0CDH DB 0C8H, 018H, 0E1H, 0C1H, 0D1H, 0C3H, 068H, 018H, 0CDH, 07EH, 017H, 0CDH, 05FH, 017H, 0C1H, 0D1H DB 0C3H, 007H, 015H, 07BH, 007H, 007H, 083H, 007H, 086H, 0D6H, 030H, 05FH, 0C3H, 07EH, 018H, 0E5H DB 021H, 03EH, 004H, 0CDH, 044H, 012H, 0E1H, 0EBH, 0AFH, 006H, 098H, 0CDH, 064H, 017H, 021H, 043H DB 012H, 0E5H, 021H, 02EH, 022H, 0E5H, 0CDH, 04DH, 017H, 036H, 020H, 0F2H, 000H, 019H, 036H, 02DH ;1900H DB 023H, 036H, 030H, 0CAH, 0B6H, 019H, 0E5H, 0FCH, 076H, 017H, 0AFH, 0F5H, 0CDH, 0BCH, 019H, 001H DB 043H, 091H, 011H, 0F8H, 04FH, 0CDH, 0C8H, 017H, 0B7H, 0E2H, 02DH, 019H, 0F1H, 0CDH, 0AAH, 018H DB 0F5H, 0C3H, 00FH, 019H, 0CDH, 095H, 016H, 0F1H, 03CH, 0F5H, 0CDH, 0BCH, 019H, 0CDH, 0F5H, 014H DB 03CH, 0CDH, 0F5H, 017H, 0CDH, 08EH, 017H, 001H, 006H, 003H, 0F1H, 081H, 03CH, 0FAH, 049H, 019H DB 0FEH, 008H, 0D2H, 049H, 019H, 03CH, 047H, 03EH, 002H, 03DH, 03DH, 0E1H, 0F5H, 011H, 0CFH, 019H DB 005H, 0C2H, 05AH, 019H, 036H, 02EH, 023H, 036H, 030H, 023H, 005H, 036H, 02EH, 0CCH, 0A3H, 017H DB 0C5H, 0E5H, 0D5H, 0CDH, 099H, 017H, 0E1H, 006H, 02FH, 004H, 07BH, 096H, 05FH, 023H, 07AH, 09EH DB 057H, 023H, 079H, 09EH, 04FH, 02BH, 02BH, 0D2H, 069H, 019H, 0CDH, 0ACH, 015H, 023H, 0CDH, 08EH DB 017H, 0EBH, 0E1H, 070H, 023H, 0C1H, 00DH, 0C2H, 05AH, 019H, 005H, 0CAH, 09AH, 019H, 02BH, 07EH DB 0FEH, 030H, 0CAH, 08EH, 019H, 0FEH, 02EH, 0C4H, 0A3H, 017H, 0F1H, 0CAH, 0B9H, 019H, 036H, 045H DB 023H, 036H, 02BH, 0F2H, 0AAH, 019H, 036H, 02DH, 02FH, 03CH, 006H, 02FH, 004H, 0D6H, 00AH, 0D2H DB 0ACH, 019H, 0C6H, 03AH, 023H, 070H, 023H, 077H, 023H, 071H, 0E1H, 0C9H, 001H, 074H, 094H, 011H DB 0F7H, 023H, 0CDH, 0C8H, 017H, 0B7H, 0E1H, 0E2H, 024H, 019H, 0E9H, 000H, 000H, 000H, 080H, 0A0H DB 086H, 001H, 010H, 027H, 000H, 0E8H, 003H, 000H, 064H, 000H, 000H, 00AH, 000H, 000H, 001H, 000H DB 000H, 021H, 076H, 017H, 0E3H, 0E9H, 0CDH, 07EH, 017H, 021H, 0CBH, 019H, 0CDH, 08BH, 017H, 0C1H DB 0D1H, 0CDH, 04DH, 017H, 078H, 0CAH, 034H, 01AH, 0F2H, 0FFH, 019H, 0B7H, 0CAH, 0A9H, 004H, 0B7H ;1A00H DB 0CAH, 06EH, 015H, 0D5H, 0C5H, 079H, 0F6H, 07FH, 0CDH, 099H, 017H, 0F2H, 01CH, 01AH, 0D5H, 0C5H DB 0CDH, 020H, 018H, 0C1H, 0D1H, 0F5H, 0CDH, 0C8H, 017H, 0E1H, 07CH, 01FH, 0E1H, 022H, 02BH, 022H DB 0E1H, 022H, 029H, 022H, 0DCH, 0E1H, 019H, 0CCH, 076H, 017H, 0D5H, 0C5H, 0CDH, 001H, 016H, 0C1H DB 0D1H, 0CDH, 042H, 016H, 0CDH, 07EH, 017H, 001H, 038H, 081H, 011H, 03BH, 0AAH, 0CDH, 042H, 016H DB 03AH, 02CH, 022H, 0FEH, 088H, 0D2H, 029H, 017H, 0CDH, 020H, 018H, 0C6H, 080H, 0C6H, 002H, 0DAH DB 029H, 017H, 0F5H, 021H, 0F0H, 015H, 0CDH, 0F8H, 014H, 0CDH, 039H, 016H, 0F1H, 0C1H, 0D1H, 0F5H DB 0CDH, 004H, 015H, 0CDH, 076H, 017H, 021H, 074H, 01AH, 0CDH, 0A4H, 01AH, 011H, 000H, 000H, 0C1H DB 04AH, 0C3H, 042H, 016H, 008H, 040H, 02EH, 094H, 074H, 070H, 04FH, 02EH, 077H, 06EH, 002H, 088H DB 07AH, 0E6H, 0A0H, 02AH, 07CH, 050H, 0AAH, 0AAH, 07EH, 0FFH, 0FFH, 07FH, 07FH, 000H, 000H, 080H DB 081H, 000H, 000H, 000H, 081H, 0CDH, 07EH, 017H, 011H, 040H, 016H, 0D5H, 0E5H, 0CDH, 099H, 017H DB 0CDH, 042H, 016H, 0E1H, 0CDH, 07EH, 017H, 07EH, 023H, 0CDH, 08BH, 017H, 006H, 0F1H, 0C1H, 0D1H DB 03DH, 0C8H, 0D5H, 0C5H, 0F5H, 0E5H, 0CDH, 042H, 016H, 0E1H, 0CDH, 09CH, 017H, 0E5H, 0CDH, 007H DB 015H, 0E1H, 0C3H, 0ADH, 01AH, 0CDH, 04DH, 017H, 021H, 05EH, 021H, 0FAH, 026H, 01BH, 021H, 07FH DB 021H, 0CDH, 08BH, 017H, 021H, 05EH, 021H, 0C8H, 086H, 0E6H, 007H, 006H, 000H, 077H, 023H, 087H DB 087H, 04FH, 009H, 0CDH, 09CH, 017H, 0CDH, 042H, 016H, 03AH, 05DH, 021H, 03CH, 0E6H, 003H, 006H DB 000H, 0FEH, 001H, 088H, 032H, 05DH, 021H, 021H, 02AH, 01BH, 087H, 087H, 04FH, 009H, 0CDH, 0F8H ;1B00H DB 014H, 0CDH, 099H, 017H, 07BH, 059H, 0EEH, 04FH, 04FH, 036H, 080H, 02BH, 046H, 036H, 080H, 021H DB 05CH, 021H, 034H, 07EH, 0D6H, 0ABH, 0C2H, 01DH, 01BH, 077H, 00CH, 015H, 01CH, 0CDH, 058H, 015H DB 021H, 07FH, 021H, 0C3H, 0A5H, 017H, 077H, 02BH, 077H, 02BH, 077H, 0C3H, 001H, 01BH, 068H, 0B1H DB 046H, 068H, 099H, 0E9H, 092H, 069H, 010H, 0D1H, 075H, 068H, 021H, 084H, 01BH, 0CDH, 0F8H, 014H DB 0CDH, 07EH, 017H, 001H, 049H, 083H, 011H, 0DBH, 00FH, 0CDH, 08EH, 017H, 0C1H, 0D1H, 0CDH, 0A3H DB 016H, 0CDH, 07EH, 017H, 0CDH, 020H, 018H, 0C1H, 0D1H, 0CDH, 004H, 015H, 021H, 088H, 01BH, 0CDH DB 0FEH, 014H, 0CDH, 04DH, 017H, 037H, 0F2H, 070H, 01BH, 0CDH, 0F5H, 014H, 0CDH, 04DH, 017H, 0B7H DB 0F5H, 0F4H, 076H, 017H, 021H, 088H, 01BH, 0CDH, 0F8H, 014H, 0F1H, 0D4H, 076H, 017H, 021H, 08CH DB 01BH, 0C3H, 095H, 01AH, 0DBH, 00FH, 049H, 081H, 000H, 000H, 000H, 07FH, 005H, 0BAH, 0D7H, 01EH DB 086H, 064H, 026H, 099H, 087H, 058H, 034H, 023H, 087H, 0E0H, 05DH, 0A5H, 086H, 0DAH, 00FH, 049H DB 083H, 0CDH, 07EH, 017H, 0CDH, 040H, 01BH, 0C1H, 0E1H, 0CDH, 07EH, 017H, 0EBH, 0CDH, 08EH, 017H DB 0CDH, 03AH, 01BH, 0C3H, 0A1H, 016H, 0CDH, 04DH, 017H, 0FCH, 0E1H, 019H, 0FCH, 076H, 017H, 03AH DB 02CH, 022H, 0FEH, 081H, 0DAH, 0D3H, 01BH, 001H, 000H, 081H, 051H, 059H, 0CDH, 0A3H, 016H, 021H DB 0FEH, 014H, 0E5H, 021H, 0DDH, 01BH, 0CDH, 095H, 01AH, 021H, 084H, 01BH, 0C9H, 009H, 04AH, 0D7H DB 03BH, 078H, 002H, 06EH, 084H, 07BH, 0FEH, 0C1H, 02FH, 07CH, 074H, 031H, 09AH, 07DH, 084H, 03DH DB 05AH, 07DH, 0C8H, 07FH, 091H, 07EH, 0E4H, 0BBH, 04CH, 07EH, 06CH, 0AAH, 0AAH, 07FH, 000H, 000H ;1C00H DB 000H, 081H, 0C9H, 0D7H, 0C9H, 03EH, 00CH, 0C3H, 03BH, 01DH, 0CDH, 0CCH, 014H, 07BH, 032H, 087H DB 021H, 0C9H, 0CDH, 06BH, 00DH, 0CDH, 0B0H, 009H, 0EDH, 053H, 08BH, 021H, 0EDH, 053H, 08DH, 021H DB 0C9H, 0CDH, 0B0H, 009H, 0D5H, 0E1H, 046H, 023H, 07EH, 0C3H, 026H, 011H, 0CDH, 06BH, 00DH, 0CDH DB 0B0H, 009H, 0D5H, 0CDH, 074H, 007H, 02CH, 0CDH, 06BH, 00DH, 0CDH, 0B0H, 009H, 0E3H, 073H, 023H DB 072H, 0E1H, 0C9H, 0CDH, 06EH, 00DH, 0CDH, 0B0H, 009H, 0C5H, 021H, 02EH, 022H, 07AH, 0FEH, 000H DB 028H, 00CH, 0CDH, 07BH, 01CH, 078H, 0FEH, 030H, 028H, 002H, 070H, 023H, 071H, 023H, 07BH, 0CDH DB 07BH, 01CH, 07AH, 0FEH, 000H, 020H, 005H, 078H, 0FEH, 030H, 028H, 002H, 070H, 023H, 071H, 023H DB 0AFH, 077H, 023H, 077H, 0C1H, 021H, 02EH, 022H, 0C3H, 0D4H, 011H, 047H, 0E6H, 00FH, 0FEH, 00AH DB 038H, 002H, 0C6H, 007H, 0C6H, 030H, 04FH, 078H, 00FH, 00FH, 00FH, 00FH, 0E6H, 00FH, 0FEH, 00AH DB 038H, 002H, 0C6H, 007H, 0C6H, 030H, 047H, 0C9H, 0EBH, 021H, 000H, 000H, 0CDH, 0B1H, 01CH, 0DAH DB 0D1H, 01CH, 018H, 005H, 0CDH, 0B1H, 01CH, 038H, 01FH, 029H, 029H, 029H, 029H, 0B5H, 06FH, 018H DB 0F3H, 013H, 01AH, 0FEH, 020H, 0CAH, 0B1H, 01CH, 0D6H, 030H, 0D8H, 0FEH, 00AH, 038H, 005H, 0D6H DB 007H, 0FEH, 00AH, 0D8H, 0FEH, 010H, 03FH, 0C9H, 0EBH, 07AH, 04BH, 0E5H, 0CDH, 025H, 011H, 0E1H DB 0C9H, 01EH, 026H, 0C3H, 0BAH, 004H, 0CDH, 06EH, 00DH, 0CDH, 0B0H, 009H, 0C5H, 021H, 02EH, 022H DB 006H, 011H, 005H, 078H, 0FEH, 001H, 028H, 008H, 0CBH, 013H, 0CBH, 012H, 030H, 0F4H, 018H, 004H DB 0CBH, 013H, 0CBH, 012H, 03EH, 030H, 0CEH, 000H, 077H, 023H, 005H, 020H, 0F3H, 0AFH, 077H, 023H ;1D00H DB 077H, 0C1H, 021H, 02EH, 022H, 0C3H, 0D4H, 011H, 0EBH, 021H, 000H, 000H, 0CDH, 025H, 01DH, 0DAH DB 033H, 01DH, 0D6H, 030H, 029H, 0B5H, 06FH, 0CDH, 025H, 01DH, 030H, 0F6H, 0EBH, 07AH, 04BH, 0E5H DB 0CDH, 025H, 011H, 0E1H, 0C9H, 013H, 01AH, 0FEH, 020H, 0CAH, 025H, 01DH, 0FEH, 030H, 0D8H, 0FEH DB 032H, 03FH, 0C9H, 01EH, 028H, 0C3H, 0BAH, 004H, 0C3H, 0EAH, 000H, 0C3H, 008H, 000H, 0C3H, 000H DB 000H, 03EH, 000H, 032H, 092H, 021H, 0C3H, 003H, 001H, 0F5H, 0A0H, 0C1H, 0B8H, 03EH, 000H, 0C9H DB 0CDH, 07FH, 007H, 0C3H, 0A6H, 00BH, 021H, 000H, 000H, 022H, 002H, 020H, 022H, 007H, 020H, 0AFH DB 032H, 004H, 020H, 032H, 005H, 020H, 032H, 006H, 020H, 021H, 090H, 000H, 07CH, 0EDH, 047H, 0EDH DB 05EH, 03EH, 0A7H, 0D3H, 010H, 03EH, 0C0H, 0D3H, 010H, 07DH, 0D3H, 010H, 0FBH, 0C9H, 0F5H, 0C5H DB 0E5H, 02AH, 002H, 020H, 001H, 005H, 000H, 009H, 001H, 0E8H, 003H, 07CH, 0B8H, 020H, 03BH, 07DH DB 0B9H, 020H, 037H, 03AH, 004H, 020H, 03CH, 032H, 004H, 020H, 0FEH, 03CH, 020H, 029H, 03AH, 005H DB 020H, 03CH, 032H, 005H, 020H, 0FEH, 03CH, 020H, 01AH, 03AH, 006H, 020H, 03CH, 032H, 006H, 020H DB 0FEH, 018H, 020H, 00BH, 02AH, 007H, 020H, 023H, 022H, 007H, 020H, 0AFH, 032H, 006H, 020H, 0AFH DB 032H, 005H, 020H, 0AFH, 032H, 004H, 020H, 021H, 000H, 000H, 022H, 002H, 020H, 0E1H, 0C1H, 0F1H DB 0FBH, 0EDH, 04DH, 03EH, 0CFH, 0D3H, 01DH, 03AH, 008H, 020H, 0D3H, 01DH, 03EH, 007H, 0D3H, 01DH DB 0C9H, 03EH, 0CFH, 0D3H, 01FH, 03AH, 00AH, 020H, 0D3H, 01FH, 03EH, 007H, 0D3H, 01FH, 0C9H, 0CDH DB 0D3H, 01DH, 03AH, 009H, 020H, 0D3H, 01CH, 0C9H, 0CDH, 0E1H, 01DH, 03AH, 00BH, 020H, 0D3H, 01EH ;1E00H DB 0C9H, 0CDH, 0CCH, 014H, 0B7H, 028H, 00BH, 0FEH, 001H, 028H, 0E4H, 0FEH, 002H, 028H, 0E9H, 0FEH DB 003H, 0C9H, 03EH, 005H, 0D3H, 01BH, 03EH, 06AH, 0D3H, 01BH, 0C3H, 000H, 000H, 0D5H, 0E5H, 0C5H DB 021H, 0EDH, 01EH, 0CDH, 044H, 012H, 0D7H, 0FEH, 003H, 0CCH, 0A6H, 00BH, 037H, 0CAH, 041H, 009H DB 0FEH, 03AH, 020H, 0F2H, 00EH, 000H, 0D7H, 0CDH, 009H, 01FH, 0DAH, 0CFH, 01EH, 087H, 087H, 087H DB 087H, 057H, 0D7H, 0CDH, 009H, 01FH, 0DAH, 0CFH, 01EH, 082H, 047H, 04FH, 0D7H, 0CDH, 009H, 01FH DB 0DAH, 0CFH, 01EH, 087H, 087H, 087H, 087H, 057H, 0D7H, 0CDH, 009H, 01FH, 0DAH, 0CFH, 01EH, 082H DB 067H, 081H, 04FH, 0D7H, 0CDH, 009H, 01FH, 0DAH, 0CFH, 01EH, 087H, 087H, 087H, 087H, 057H, 0D7H DB 0CDH, 009H, 01FH, 0DAH, 0CFH, 01EH, 082H, 06FH, 081H, 04FH, 0D7H, 0CDH, 009H, 01FH, 0DAH, 0CFH DB 01EH, 087H, 087H, 087H, 087H, 057H, 0D7H, 0CDH, 009H, 01FH, 0DAH, 0CFH, 01EH, 082H, 0FEH, 001H DB 0CAH, 0DAH, 01EH, 0D7H, 0CDH, 009H, 01FH, 0DAH, 0CFH, 01EH, 087H, 087H, 087H, 087H, 057H, 0D7H DB 0CDH, 009H, 01FH, 0DAH, 0CFH, 01EH, 082H, 077H, 081H, 04FH, 023H, 010H, 0E6H, 079H, 02FH, 03CH DB 04FH, 0D7H, 0CDH, 009H, 01FH, 0DAH, 0CFH, 01EH, 087H, 087H, 087H, 087H, 057H, 0D7H, 0CDH, 009H DB 01FH, 0DAH, 0CFH, 01EH, 082H, 0B9H, 0C2H, 0CFH, 01EH, 03EH, 02AH, 0CFH, 0C3H, 026H, 01EH, 021H DB 0F6H, 01EH, 0CDH, 044H, 012H, 0E1H, 0D1H, 0C3H, 0DDH, 000H, 0D7H, 0FEH, 00DH, 020H, 0FBH, 0CDH DB 0A6H, 00BH, 021H, 000H, 01FH, 0CDH, 044H, 012H, 0E1H, 0D1H, 0C3H, 0DDH, 000H, 052H, 045H, 041H DB 044H, 059H, 00DH, 00AH, 000H, 000H, 046H, 041H, 049H, 04CH, 045H, 044H, 00DH, 00AH, 000H, 000H ;1F00H DB 045H, 04EH, 044H, 045H, 044H, 00DH, 00AH, 000H, 000H, 0FEH, 030H, 0D8H, 0FEH, 03AH, 038H, 009H DB 0FEH, 041H, 0D8H, 0FEH, 047H, 03FH, 0D8H, 0C6H, 009H, 0E6H, 00FH, 0C9H, 0F5H, 0C5H, 0D5H, 0E5H DB 032H, 00DH, 020H, 0EDH, 043H, 00FH, 020H, 0EDH, 053H, 011H, 020H, 022H, 013H, 020H, 0E1H, 0D1H DB 0C1H, 0F1H, 0C9H, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH DB 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH, 0FFH BSRAM1: END