toString: ld a,(hl) con1: call memAssert cp tadd jp z,conA cp tsub jp z,conS con2: call memAssert cp tmul jp z,conM cp tdiv jp z,conD cp 0b0h jr z,conneg con3: call memAssert cp tpower jp z,conE con4: call memAssert or a jr z,conNum ;add negate cp 128 jr z,conNum cp 1 jr z,conVar call isOpenParen jr z,paren2 ld de,(freeRam) ld a,tlparen ld (de),a inc de ld (freeRam),de paren1: call memAssert call toString ld de,(freeRam) ld a,trparen ld (de),a inc de ld (freeRam),de ret conneg: ld de,(freeRam) ld (de),a inc de ld (freeRam),de inc hl ld e,(hl) inc hl ld d,(hl) ex de,hl ld a,(hl) jr con2 paren2: ld a,(hl) ld de,(freeRam) cp 0CFh jr c,tostring1byte push af ld a,0BBh ld (de),a inc de pop af tostring1byte: ld (de),a inc de ld (freeRam),de inc hl ld e,(hl) inc hl ld d,(hl) ex de,hl ld a,(hl) jr paren1 conVar: inc hl ld a,(hl) ld de,(freeRam) cp tFakeExp jr nz,conVar2 ld a,0BBh ld (de),a inc de ld a,31h conVar2: ld (de),a inc de ld (freeRam),de ret conNum: rst rmov9toop1 ld a,(iy+fmtFlags) ld (iy+fmtOverride),a B_CALL formbase ld de,(freeRam) push de push bc ld hl,op3 ldir ld (freeRam),de pop bc pop hl ;need to tokenize these number just converted conNum20: dec hl inc c conNum2: inc hl dec c ret z ld a,(hl) cp 02eh jr nz,nextcom ld (hl),tdecpt nextcom: cp 01ah jr nz,lstcom ld (hl),0b0h lstcom: cp 01Bh jr nz,conNum3 ld (hl),tee conNum3: cp lneg jr nz,conNum2 ld (hl),0B0h jr conNum2 conA: call precon call con1 call memAssert ld a,tadd call postcon jp con1 conM: call precon call con2 call memAssert ld a,tmul jr conM2 ; call postcon ; jp con2 conS: call precon call con2 call memAssert ld a,tsub conM2: call postcon jp con2 conD: call precon call con2 call memAssert ld a,tdiv call postcon jp con3 conE: call precon call con4 call memAssert ld a,tpower call postcon jp con4 precon: inc hl ld e,(hl) inc hl ld d,(hl) pop bc push hl push bc ex de,hl ld a,(hl) ret postcon: ld de,(freeRam) ld (de),a inc de ld (freeRam),de pop bc pop hl push bc inc hl ld e,(hl) inc hl ld d,(hl) ex de,hl ld a,(hl) ret findEONest: push de dec bc ;to catch up with hl ld a,b or c jp z,syntaxErr ld d,1 ;open paren count so we don't get thrown off by nested ones findEONest2: ld a,(hl) cp trparen jr z,endParenFound call isOpenParen jr nz,moreParen2go inc d moreParen2go: inc hl dec bc ld e,a ld a,b or c ld a,e jp z,syntaxErr jr findEONest2 endParenFound: dec d jr nz,moreParen2go pop de inc hl ret ;checks to see if the token is part of a number ;input: ; a = token we're comparing isNum: ;optiminze... don't return a=0 or 1, just a flag ld b,12 isNumNoB: ex de,hl ld hl,num_vals-1 ld c,0 isNum2: inc hl cp (hl) jr z,isNum3 cp 03ah jr z,decFound isNum4: dec b jr nz,isNum2 inc c isNum3: ld a,c ex de,hl ret decFound: set decimal,(IY+myFlags) jr isNum4 ;checks for open parentheses so we can skip that expression ;input: ; a = token we're comparing isOpenParen: push hl push bc ld hl,OpenParen ; ld bc,19 ld bc,33 cpir pop bc pop hl ret stringtonum: B_CALL zeroop1 ld ix,op1+2 ld a,07fh ld (ix-1),a pop bc pop hl ;make sure it doesn't start with an e ld a,(hl) cp tee jp z,syntaxErr ld e,0 ;0 if no decimal yet. ;need to ignore any zeros preceeding the number dec hl inc bc ignorezeros: dec bc inc hl ld a,(hl) cp t0 jr z,ignorezeros2 cp tdecpt jr nz,stringtonum0 ;it is a decpnt ld a,e or a jp nz,syntaxErr ld e,1 jr ignorezeros ignorezeros2: ld a,e or a jr z,ignorezeros ;decrement mantissa push hl ld hl,op1+1 dec (hl) pop hl jr ignorezeros stringtonum0: ld d,7 ;number of bytes to copy to op1 stringtonum2: ld a,b or c jr z,numStringDone ld a,(hl) inc hl dec bc cp t0 jr c,notANum cp t9+1 jr nc,notANum sub t0 rl a rl a rl a rl a ld (ix),a xor a or e call z,incrementmantissa stringtonum3: ld a,b or c jr z,numStringDone ld a,(hl) inc hl dec bc cp t0 jr c,notANum2 cp t9+1 jr nc,notANum2 sub t0 or (ix) ld (ix),a inc ix xor a cp e call z,incrementmantissa dec d jr nz,stringtonum2 ;well op1 is full now but we might not have reached the end of the number iteratenum: ld a,b or c jr z,numStringDone ld a,(hl) inc hl dec bc cp t0 jr c,notANum3 cp t9+1 jr nc,notANum3 xor a cp e call z,incrementmantissa jr iteratenum notANum3: cp tdecpt jr z,isaDecPt3 cp tee jp nz,syntaxErr jr getexponent isaDecPt3: xor a cp e jp nz,syntaxErr ld e,1 jr iteratenum numStringDone: ld de,(freeRam) push de ; ld hl,op1 ; ld bc,9 ; ldir B_CALL movfrop1 ld (freeRam),de pop hl ret notANum: cp tdecpt jr nz,notdecpt xor a cp e jp nz,syntaxErr ld e,1 jp stringtonum2 notdecpt: cp tee jr z,getexponent notANum2: cp tdecpt jr nz,notdecpt ;this poses a small problem. its an infinite loop! xor a cp e jp nz,syntaxErr ld e,1 jr stringtonum3 getexponent: ld d,0 ld a,(hl) cp 0b0h jr nz,notnegexponent inc hl inc d dec bc notnegexponent: ld a,b or a jp nz,syntaxErr ld e,0 ld a,c cp 3 jp nc,syntaxErr cp 1 jp c,syntaxErr dec c jr z,onlydigitee ld a,(hl) cp t0 jp c,syntaxErr cp t9+1 jp nc,syntaxErr sub t0 add a,a ld e,a add a,a add a,a add a,e ld e,a inc hl onlydigitee: ld a,(hl) cp t0 jp c,syntaxErr cp t9+1 jp nc,syntaxErr sub t0 add a,e ld e,a xor a cp d jr z,posee ld a,(op1+1) sub e jr eedone posee: ld a,(op1+1) add a,e eedone: ld (op1+1),a jp numStringDone incrementmantissa: push hl ld hl,op1+1 inc (hl) pop hl ret ;input: ; de = loc of subtree to copy ;output: ; de = loc of new tree copySub: ;* call memAssert ;* ld hl,(freeRam) push hl push hl ex de,hl ld a,(hl) call isOpenParen ; or a jr z,copyFunc ld a,(hl) cp 0b0h jr z,copyFunc or a jr z,copyNum cp 1 jr z,copyVar ex de,hl inc hl inc hl inc hl inc hl inc hl ld (freeRam),hl pop hl ld (hl),a inc hl push hl ;freeRAm+1 ex de,hl inc hl ld e,(hl) inc hl ld d,(hl) push hl ;node+2 call copySub pop ix ;ix=node+2 pop hl ;hl=freeRam+1 ld (hl),e inc hl ld (hl),d inc hl push hl ;freeRAm+3 ld e,(ix+1) ld d,(ix+2) call copySub pop hl ld (hl),e inc hl ld (hl),d pop de ret copyFunc: ld a,(hl) ex de,hl inc hl inc hl inc hl ld (freeRam),hl pop hl ld (hl),a inc hl push hl ex de,hl inc hl ld e,(hl) inc hl ld d,(hl) call copySub pop hl ld (hl),e inc hl ld (hl),d pop de ret copyNum: pop de ; ld bc,9 ; ldir B_CALL mov9b ld (freeRam),de pop de ret copyVar: ; pop de ; ld bc,2 ; jr copyLittle ex de,hl pop af pop af ret ;input: hl= start of tree to invert invASTree: ;* call memAssert ;* ld a,(hl) cp tadd jr z,invASTree2 cp tsub ret nz dec (hl) jr invASTree3 invASTree2: inc (hl) invASTree3: inc hl ld e,(hl) inc hl ld d,(hl) push hl ex de,hl call invASTree pop hl inc hl ld e,(hl) inc hl ld d,(hl) ex de,hl jp invASTree ;input: hl = tree ; op1 = coeff ;output: bc = top of tree insertCoeff: push hl ld a,(hl) or a jp z,insertCoeff3 cp tmul jp nz,insertCoeff2 inc hl ld e,(hl) inc hl ld d,(hl) ex de,hl ld a,(hl) or a jp nz,insertCoeff2 insertCoeff3: ex de,hl ; ld hl,op1 ; ld bc,9 ; ldir B_CALL movfrop1 pop bc ret insertCoeff2: ld de,(freeRam) push de ; ld hl,op1 ; ld bc,9 ; ldir B_CALL movfrop1 ex de,hl ld (hl),tmul push hl pop bc inc hl pop de ld (hl),e inc hl ld (hl),d inc hl pop de ld (hl),e inc hl ld (hl),d inc hl ld (freeRam),hl ret ;in: hl = pointer to term ; de = pointer to exponent ;out: ; hl = pointer to term w/ exp insertExp: ld a,(hl) cp tpower jp nz,insertExp2 push hl inc hl inc hl inc hl ld (hl),e inc hl ld (hl),d pop hl ret insertExp2: push hl pop bc ld hl,(freeRam) push hl ld (hl),tpower inc hl ld (hl),c inc hl ld (hl),b inc hl ld (hl),e inc hl ld (hl),d inc hl ld (freeRam),hl pop hl ret ;in: hl = pointer to term ;out: hl = pointer to coeff getCoeff: ld a,(hl) or a ret z cp tmul jp nz,getCoeff2 inc hl ld e,(hl) inc hl ld d,(hl) ex de,hl ld a,(hl) or a ret z getCoeff2: ld hl,aOne ret ;in: ; hl and de both = terms ;out: ; z if equal, nz if not cmpIgPow: call cmpIgPow2 ex de,hl call cmpIgPow2 jp cmpTree cmpIgPow2: ld a,(hl) cp tpower ret nz inc hl ld c,(hl) inc hl ld b,(hl) push bc pop hl ret ;in: hl = term ;out de = power getPower: ld a,(hl) cp tpower jp nz,makeOne inc hl inc hl inc hl ld e,(hl) inc hl ld d,(hl) ret cmpIgCoef: ;stips off first coeff ld a,(hl) or a jp z,getCoeff2 cp tmul ret nz push hl inc hl ld c,(hl) inc hl ld b,(hl) push bc pop hl ld a,(hl) or a jp nz,cmpIgCoeff2 pop ix ld l,(ix+3) ld h,(ix+4) ret cmpIgCoeff2: pop hl ret cmpIgCoeff: call cmpIgCoef ex de,hl call cmpIgCoef ;input: ; hl = tree 1 ; de = tree 2 ;ouput: ; z if equal ; we'll see if i need to do a priority compare cmpTree: ;* call memAssert ;* ld a,(hl) ld b,a ex de,hl ld a,(hl) ex de,hl cp b ret nz cp 080h jr z,cmpTree20 or a jr nz,cmpTree2 cmpTree20: ;need to check if numbers are the same..... ld c,8 cmpTree21: inc de inc hl ld a,(hl) ld b,a ex de,hl ld a,(hl) ex de,hl cp b ret nz dec c jr nz,cmpTree21 ret cmpTree2: cp 1 jr nz,cmpTree3 ;not a variable inc hl inc de ld a,(hl) ld b,a ex de,hl ld a,(hl) cp b ret cmpTree3: push af push de pop ix ld e,(ix+1) ld d,(ix+2) push ix push hl pop ix ld l,(ix+1) ld h,(ix+2) push ix call cmpTree pop hl pop hl pop hl ret nz dec sp dec sp dec sp dec sp dec sp dec sp pop ix ld l,(ix+3) ld h,(ix+4) pop ix ld e,(ix+3) ld d,(ix+4) pop af cp 0b0h ;neg sign has only 1 arg ret z call isOpenParen ret z call cmpTree ret ;input: none ;output: de=pointer to 1 ;destroys: hl,de,bc makeOne: ;* call memAssert ;* ld de,(freeRam) push de ld hl,aOne ld bc,9 ldir ld (freeRam),de pop de ret ;input: none ;output: de=pointer to 0 ;destroys: hl,de,bc makeZero: ;* call memAssert ;* ld de,(freeRam) push de ld hl,aZero ld bc,9 ldir ld (freeRam),de pop de ret ;these could use some optimiazing... also there might be other routines that made their own 2's... makeTwo: ;* call memAssert ;* ld de,(freeRam) push de ld hl,aTwo ld bc,9 ldir ld (freeRam),de pop de ret ;double check to see if all these are used op1toop7: OP1ToOP7: ld hl,op1 toop7: ld de,op7 opcall: ld bc,9 ldir ret op7toop1: OP7ToOP1: ld de,op1 op7to: ld hl,op7 jr opcall OP7ToOP2: ld de,op2 jr op7to OP6ToOP7: ld hl,op6 jr toop7 OP1ToOP8: ld hl,op1 ld de,op8 jr opcall OP8ToOP1: ld hl,op8 ld de,op1 jr opcall DispRLE: ld bc,768 ; we need to copy (768 for normal pics) DispRLEL: DispRLEL2: ld a,(hl) ; get the next byte cp 91h ; is it a run? jr z,DispRLERun2 ; then we need to decode the run ldi ; copy the byte, and update counters DispRLEC2: ret po ; ret if bc hit 0 jr DispRLEL2 ; otherwise do next byte DispRLERun2: inc hl inc hl ; move to the run count ld a,(hl) ; get the run count DispRLERunL2: dec hl ; go back to run value dec a ; decrease run counter ldi ; copy byte, dec bc, inc de, inc hl jr nz,DispRLERunL2 ; if we're not done, then loop inc hl ; advance the source pointer jr DispRLEC2 ; check to see if we should loop memAssert: bit oninterrupt,(iy+onflags) jp nz,breakErr push hl push de ld de,(imathptr2) ld (stack),sp ld hl,(stack) memAssertCommon: or a sbc hl,de jp z,notEnMemErr ld de,100 or a sbc hl,de jp c,notEnMemErr pop de pop hl ret ;used only in demess cause the stack is still where the os intializes it to be and we don't ;want to overwrite the vat while placing new * where multiplication is implied memAssert2: push hl push de ld de,(imathptr2) ld hl,(imathptr3) jr memAssertCommon