diff --git a/16bitplayer.asm b/16bitplayer.asm new file mode 100644 index 0000000..c9724fd --- /dev/null +++ b/16bitplayer.asm @@ -0,0 +1,907 @@ + +play + call waitForKeyRelease ;keyhandler is very fast, so make sure there are currently no keys pressed + +init ;sandboxing the actual player so we can handle keypresses vs looping quickly + ld de,ptns +initrp ;init point for row play + push de + call resetFX + + ld hl,(musicData+1) ;load user (drum) sample pointer \ this will become redundant, (usrdrum) can be set on loading song + ld (usrdrum),hl ;save it to drum table / and if song is already in mem, it is then also already loaded + + ld a,(looprow) ;set loop point + add a,a ;A*4 + add a,a + ld l,a + ld h,0 + ld de,ptns + + ld a,(de) ;while we're at it, check if player is set to start from an empty row (first pattern # = #ff) + ;inc a + ;ret z ;and exit if so + + add hl,de ;else, continue calculating loop point + ld (looppoint),hl + pop de + + inc a ;continue "empty row" check + ret z + + call rdnotes1 + +init0 + call rdnotes0 + + jp z,init0 ;loop if no key pressed + +;************************************************************************************* +rdnotes0 ;initialize read song data process +looppoint equ $+1 + ld de,0 ;point song data pointer at loop point + + ld a,(de) ;check if loop point is still valid - exit with error if not + inc a + jp z,lpInvalidErr + +rdnotes1 + push de ;preserve song data pointer + xor a + out (kbd),a + jr ptnselect + +;************************************************************************************* +ptnselect0 + pop hl ;clean stack - PROBABLY BETTER TO USE LD SP,nnnn + pop hl + pop hl + pop hl +;************************************************************************************* +ptnselect ;FIRST, set up ptn sequence pointers and push them (preserve song seq pointer in mem?) + ;SECOND, check if row counter has reached 0 + ;THIRD, pop back ptn sequence pointers and read in data + + ld a,#11 ;7 ;initialize ptn position counter - all patterns are 16 rows long + ld (reptpos),a ;13 + + pop de ;10 ;restore song data pointer + + ld a,(de) ;7 ;load ptn# ch1 + cp #ff ;7 ;check for end marker + ret z ;11/5 ;exit if found + + + ;ld hl,ptntab ;10 ;point to pattern position LUT + ld h,HIGH(ptntab) + add a,a ;4 ;A=A*2 + ;add a,l ;4 + ld l,a ;4 + ;jr nc,psskip1 ;12/7 + ;inc h ;4 + +psskip1 + ld c,(hl) ;7 ;seq pointer ch1 to bc + inc hl ;6 + ld b,(hl) ;7 + push bc ;11 + + + inc de ;6 ;point to ch3 + ld a,(de) ;7 ;load ptn# ch3 + ;ld hl,ptntab ;10 + add a,a ;4 + ;add a,l ;4 + ld l,a ;4 + ;jr nc,psskip2 ;12/7 + ;inc h ;4 + +psskip2 + ld c,(hl) ;7 ;seq pointer ch3 to bc + inc hl ;6 + ld b,(hl) ;7 + push bc ;11 + + + inc de ;6 ;point to ch2 + ld a,(de) ;7 ;load ptn# ch2 + ;ld hl,ptntab ;10 + add a,a ;4 + ;add a,l ;4 + ld l,a ;4 + ;jr nc,psskip3 ;12/7 + ;inc h ;4 + +psskip3 + ld c,(hl) ;7 ;seq pointer ch2 to bc + inc hl ;6 + ld b,(hl) ;7 + push bc ;6 + + + inc de ;6 ;point to fx + ld a,(de) ;7 ;load ptn# fx + ld hl,fxptntab ;10 + add a,a ;4 + add a,l ;4 + ld l,a ;4 + jr nc,psskip4 ;12/7 + inc h ;4 +psskip4 + ld c,(hl) ;7 ;seq pointer fx to bc + inc hl ;6 + ld b,(hl) ;7 + + + inc de ;6 ;point to next row + + exx ;4 + + pop bc ;10 ;seq pointer ch2 to bc' + pop de ;10 ;seq pointer ch3 to de' + pop hl ;10 ;seq pointer ch1 to hl' + + exx ;4 + + push de ;11 ;stack loc. 1 - sng seq pointer + push bc ;11 ;stack loc. 2 - fx ptn pointer + + exx ;4 + + push bc ;11 ;stack loc. 3 - ch2 ptn pointer + push de ;11 ;stack loc. 4 - ch3 ptn pointer + push hl ;11 ;stack loc. 5 - ch1 ptn pointer + +;************************************************************************************* +rdnotes ;read in next step from song data + ;ch1 - sp, ch2 - de, ch3 - bc, speed - de' +reptpos equ $+1 + ld a,0 ;7 ;decrement pattern row counter + dec a ;4 + jr z,ptnselect0 ;12/7 ;if it has reached 0, move on to the next pattern -> NEED TO CORRECT STACK BEFORE JUMP!!! + ld (reptpos),a ;13 ;TODO: using DEC (HL) will be faster + +rdnotesRP ;entry point for RowPlay + ld hl,NoteTab ;10 ;point to frequency LUT + + pop bc ;10 ;ch1 ptn pointer to bc + ld a,(bc) ;7 + inc bc ;6 ;increment ptn pos pointer + add a,a ;4 + add a,l ;4 ;get offset in frequency LUT + ld l,a ;4 + + ld a,(hl) ;7 ;lookup lo byte of frequency value + add a,a ;4 ;for channel 1, values are multiplied by 2 + ld (ch1),a ;13 ;and store it to base counter + inc l ;4 + ;ld a,0 ;7 ;preserve carry + ld a,(hl) + adc a,(hl) ;7 ;lookup and double add hi byte of frequency vaule + ;add a,(hl) ;7 ;done: how about ld a,(hl), adc a,(hl)? + ld (ch1+1),a ;13 ;and store it to base counter + + ld l,0 ;7 ;reset freq.LUT pointer + pop de ;10 ;ch3 ptn pointer to de + ld a,(de) ;7 + inc de ;6 ;increment ptn pos pointer + rla ;4 ;can use rla here since carry is reset from previous add a,l op + add a,l ;4 + ld l,a ;4 + + ld a,(hl) ;7 + ld (ch3),a ;13 + inc l ;4 + ld a,(hl) ;7 + ld (ch3+1),a ;13 + + exx ;4 + + ld hl,NoteTab ;10 ;reset freq.LUT pointer + pop bc ;10 ;ch2 ptn pointer to bc' + ld a,(bc) ;7 + inc bc ;6 + rla ;4 + add a,l ;4 + ld l,a ;4 + + ld a,(hl) ;7 + ld (ch2),a ;13 + inc l ;4 + ld a,(hl) ;7 + ld (ch2+1),a ;13 + + pop de ;10 ;fx ptn pointer to de + ld a,(de) ;7 ;read fx# + + and %11110000 ;7 ;check for drum trigger (lower nibble) + jp nz,drums ;17/10 + + ld hl,drumres ;10 ;reset drum by setting pointer to a 0 val TODO: seems messy, optimize + ld (drumtrig),hl ;16 ; TODO: ^^ + +drx + ld a,(de) ;7 + and %00001111 ;7 ; + inc de ;6 ;point to fx parameter + jp nz,fxselect ;10 + +fxcont + inc de ;6 ;point to next row + + push de ;11 ;stack 2 + push bc ;11 ;stack 3 + + ld bc,0 ;10 ;BC' is add value for ch2, zero it + +ch2 equ $+1 + ld de,0 ;10 ;DE' holds the base counter for ch3 + + ld iy,0 ;14 ;IY is the add value for ch3, zero it + + exx ;4 + push de ;11 ;stack 4 + push bc ;11 ;stack 5 + +drumtrig equ $+1 + ld bc,0 ;10 + +cspeed equ $+2 + ld de,#1000 ;10 ;speed + + ld (oldSP),sp ;20 ;preserve SP --> TODO: calculate this on entering player +ch1 equ $+1 + ld sp,#0000 ;10 ;load base frequency counter val + ld (counterSP),sp ;20 ;TODO: maybe remove, it's not that important... + +drumres equ $+1 + ld hl,0 ;10 ;HL holds "add" value for ch1, zero it; the 0-word also acts as stop byte for the drums + ;TODO: seems messy (see above) + +mask1 equ $+2 ;panning switches for drum and ch1 +maskD equ $+3 + ld ix,lp_msk ;14 ;initialize output masks for those channels that use it (set to all channels off) + +;************************************************************************************* +playnote ;synthesize and output current step + + ld a,(bc) ;7 ;load sample byte +drumswap2 + nop ;4 ;daa/cpl/etc +dru equ $+1 + add a,0 ;7 ;add current drum pitch counter + ld (dru),a ;13 ;and save it as current pitch counter + +volswap1 equ $+1 + ld a,ixh ;8 ;output mask for drum channel - ld a,ixh = dd 7c, ld a,ixl = dd 7d + out (link),a ;11 ;output drum channel state + ;---- CH2: 104t +muteD ;mute switch for drums + jr nc,waitD ;12/7 ;skip the following if result was <=#ff + +drumswap ;switch for drum mode. inc bc = #03, dec bc = #0b, inc c = #0c, dec c = #0d, nop + inc bc ;6 ;increment sample data pointer +panD equ $+1 + xor lp_sw ;7 ;toggle output mask + ld ixh,a ;8 ;and update it + ;28t +outdr +;volswap2 equ $+1 + ld a,ixl ;8 ;load output mask ch1 - ld a,ixl = dd 7d, ld a,ixh = dd 7c, or ixl = dd b5, and ixl = dd a5 + add hl,sp ;11 ;add current counter to base freq.counter val. ch1 and save result in HL +mute1 ;mute switch for ch1 + jr nc,out1 ;12/7 ;skip the following if result was <=#ffff + ;else +pan1 equ $+1 + xor lp_sw ;7 ;toggle output mask ch1 + ld ixl,a ;8 ;and update it +out1 + out (link),a ;11 ;output state ch1 + ;----- DRUMS: 77/78/87/88t (old 85/95t) (old 105/115t) + exx ;4 ;back to the normal register set + + add iy,de ;15 ;this is actually ch3 +phaseshift3 equ $+1 ;switch for phase shift/set duty cycle + ld a,#80 ;7 + cp iyh ;8 +mute3 + sbc a,a ;4 ;result of this will be either #00 or #ff. for mute, swap #9f (sbc a,a) with #97 (sub a,a) + or lp_off ;7 ;TODO: useless on 8x, maybe can be eliminated on other models, too? +pan3 equ $+1 + and lp_on ;7 ;and thus we derive the output state +pitchslide equ $+1 + ld hl,0 ;10 ;switch for pitch slide + add hl,de ;11 + ex de,hl ;4 +out3 + out (link),a ;11 + ;---- CH1: 88t + +ch3 equ $+1 + ld hl,#0000 ;10 ;and now, same as above but for ch2 + add hl,bc ;11 + ld b,h ;4 + ld c,l ;4 +phaseshift2 equ $+1 + ld a,#80 ;7 +pwmswitch ;ch2 PWM effect switch + add a,0 ;7 ;add a,n = #c6; adc a,n = #ce + ld (phaseshift2),a ;13 + cp b ;4 +mute2 + sbc a,a ;4 + or lp_off ;7 ;TODO: useless on 8x, maybe can be eliminated on other models, too? +pan2 equ $+1 + and lp_on ;7 +out2 + out (link),a ;11 + ;---- CH3: 89t +readkeys ;check if a key has been pressed + in a,(kbd) ;11 + cpl ;4 ;COULD IN THEORY OPTIMIZE THIS AWAY + or a ;4 + jr nz,keyPressed ;12/7 ;and exit if necessary + +reentry + exx ;4 + +; dec de +; ld a,d +; or e +; jp nz,playnote + dec e ;4 ;update speed counter - slightly inefficient, but faster on average than dec de\ld a,d\or e, and gives better sound + jr nz,playnote ;12/7 ;TODO: worth using jp??? worth retracting to dec de..? (+8t)? + ; + dec d ;4 + jp nz,playnote ;10 + ; +;************************************************************************************* +keyPressed +oldSP equ $+1 + ld sp,0 ;retrieve SP +rowplaySwap equ $+1 ;switch for jumping to exitRowplay instead, jp z = #ca, ret = #c9 + jp z,rdnotes ;z-flag will be set when speed counter has reached 0 + + push de ;preserve all counters + push bc + exx + push de + push hl + push bc + + call keyhand + + pop bc ;retrieve all counters + pop hl + pop de + exx + pop bc + pop de + +counterSP equ $+1 + ld sp,0 + + xor a + out (kbd),a + + jp reentry ;and continue playing + +;************************************************************************************* +waitD +fxswap1 +fxswap2 equ $+1 + ld a,4 ;7 ;swap with rlc h (cb 04) for noise/glitch effect, with rlc l (cb 05) for phase effect - ld a,n = c6 + jp outdr ;10 + ;17+12=29 + +;************************************************************************************* +drums ;select drum + ld hl,samples-2 ;point to beginning of sample pointer table - 2 (because minimum offset will be +2) + rra ;divide drum # by 8 to get offset in table (carry is cleared before calling drum select) + rra + rra + add a,l ;add offset to (h)l + ld l,a + ld a,(hl) ;load drum data pointer into bc + ld (drumtrig),a + inc l + ld a,(hl) + ld (drumtrig+1),a + jp drx + +;************************************************************************************* +fxselect ;select fx + dec a ;calculate jump + add a,a + add a,a + ld (_jump),a +_jump equ $+1 + jr $ + +fxJumpTab + jp fx1 + nop + jp fx2 + nop + jp fx3 + nop + jp fx4 + nop + jp fx5 + nop + jp fx6 + nop + jp fxcont ;fx7 + nop + jp fxcont ;fx8 + nop + jp fxcont ;fx9 + nop + jp fxA + nop + jp fxB + nop + jp fxC + nop + jp fxD + nop + jp fxE + nop + +fxF ;#0f = set speed + ld a,(de) + ld (cspeed),a + jp fxcont + +fxB ;#0b = break cmd + ld a,(reptpos) + cp #10 + jp nz,ptnselect ;10 ;select next ptn if found ATTN: leaves register set swapped! + jp fxcont + +fx1 ;#01 = set panning + ld a,(de) + +pch1 + rrca + jp c,setright1 + rrca + jp c,setleft1 + ex af,af' + ld a,lp_sw + ld (pan1),a + ld a,lp_off + ld (mask1),a + ex af,af' + +pch2 + rrca + jp c,setright2 + rrca + jp c,setleft2 + ex af,af' + ld a,lp_on + ld (pan2),a + ex af,af' + +pch3 + rrca + jp c,setright3 + rrca + jp c,setleft3 + ex af,af' + ld a,lp_on + ld (pan3),a + ex af,af' + +pchD + rrca + jp c,setrightD + rrca + jp c,setleftD + ex af,af' + ld a,lp_sw + ld (panD),a + ld a,lp_off + ld (maskD),a + ex af,af' + jp fxcont + +fx2 ;pitch slide up + ld a,(de) + ld (pitchslide),a + xor a + ld (pitchslide+1),a + jp fxcont + +fx3 ;pitch slide up + ld a,(de) + neg + ld (pitchslide),a + ld a,#ff + ld (pitchslide+1),a + jp fxcont + +fx4 ;ch2 pwm mode + ld a,(de) + or a + jr z,_resetpwm + ld a,#ce + ld (pwmswitch),a + jp fxcont +_resetpwm + ld a,#c6 + ld (pwmswitch),a + ld a,#80 + ld (phaseshift2),a + jp fxcont + +fx5 ;duty cycle ch2 + ld a,(de) + ld (phaseshift2),a + jp fxcont + +fx6 ;duty cycle ch3 + ld a,(de) + ld (phaseshift3),a + jp fxcont + +fxA ;ch1 "glitch" effect + ld a,(de) + or a + jr z,_Askip + dec a + ld a,5 + jr nz,_Afast + + dec a +_Afast + ld (fxswap2),a + ld a,#cb + ld (fxswap1),a + jp fxcont +_Askip + ld a,#c6 + ld (fxswap1),a + jp fxcont + + +fxC ;set drum mode. + ld a,(de) + and #0f ;calculate jump + add a,a + add a,a + ld (_jumpx),a +_jumpx equ $+1 + jr $ + +_fxCx0 + ld a,0 ;nop (default) + jr _fxCxx +_fxCx1 + ld a,#27 ;daa + jr _fxCxx +_fxCx2 + ld a,#8f ;add a,a + jr _fxCxx +_fxCx3 + ld a,#1f ;rra + jr _fxCxx +_fxCx4 + ld a,#2f ;cpl + jr _fxCxx +_fxCx5 + ld a,#79 ;ld a,c + jr _fxCxx +_fxCx6 + ld a,#89 ;add a,c + jr _fxCxx +_fxCx7 + ld a,#88 ;add a,b + jr _fxCxx +_fxCx8 + ld a,#90 ;sub b + jr _fxCxx +_fxCx9 + ld a,#91 ;sub c + jr _fxCxx +_fxCxa + ld a,#a0 ;and b + jr _fxCxx +_fxCxb + ld a,#a1 ;and c + jr _fxCxx +_fxCxc + ld a,#b0 ;or b + jr _fxCxx +_fxCxd + ld a,#b1 ;or c + jr _fxCxx +_fxCxe + ld a,#a8 ;xor b + jr _fxCxx +_fxCxf + ld a,#a9 ;xor c + +_fxCxx + ld (drumswap2),a + ld a,(de) + and #70 + cp #41 ;if high nibble > 4, ignore + jp nc,fxcont + + ccf ;calculate jump + rra + rra + ld (_jump),a + +_jump equ $+1 + jr $ + +_fxC0x + ld a,#03 ;inc bc + jr _fxCyy +_fxC1x + ld a,#0b ;dec bc + jr _fxCyy +_fxC2x + ld a,#0c ;inc c + jr _fxCyy +_fxC3x + ld a,#0d ;dec c + jr _fxCyy +_fxC4x + xor a ;nop + +_fxCyy + ld (drumswap),a + jp fxcont + +fxD ;ch1/d volume shift +; ld a,(de) +; or a +; jr z,_Vreset +; +; dec a ;D01 = double vol ch1 +; jr nz,_fxD2 +; ld a,#7d +; _fxDxx +; ld (volswap2),a +; ld (volswap1),a +; jp fxcont +; +; _fxD2 ;D02 = double vol drums +; dec a +; jr nz,_fxD3 +; ld a,#7c +; jr _fxDxx +; +; _fxD3 ;D03 = drums OR ch1 +; dec a +; ld a,#7c +; ld (volswap1),a +; jr nz,_fxD4 +; ld a,#b5 +; db #c2 ;jp nz,... +; +; +; _fxD4 ;D04 = drums AND ch1 +; ld a,#a5 +; ld (volswap2),a +; jp fxcont +; +; _Vreset +; ld a,#7c +; ld (volswap1),a +; inc a +; ld (volswap2),a +; jp fxcont + + jr nz,_Vskip + ld a,#7c + db #c2 +_Vskip + ld a,#7d + ld (volswap1),a + jp fxcont + +fxE ;reset all fx + ld a,(de) + or a + call z,resetFX ;resetFX always returns with A=0 and Z-flag set + dec a + call z,resetFX1 + dec a + call z,resetFX2 + call nz,resetFX3 + jp fxcont + +setright1 + ex af,af' + ld a,lp_swr + ld (pan1),a + ld a,lp_r + ld (mask1),a + ex af,af' + rrca + jp pch2 + +setleft1 + ex af,af' + ld a,lp_swl + ld (pan1),a + ld a,lp_l + ld (mask1),a + ex af,af' + jp pch2 + +setright2 + ex af,af' + ld a,lp_r + ld (pan2),a + ex af,af' + rrca + jp pch3 + +setleft2 + ex af,af' + ld a,lp_l + ld (pan2),a + ex af,af' + jp pch3 + +setright3 + ex af,af' + ld a,lp_r + ld (pan3),a + ex af,af' + rrca + jp pchD + +setleft3 + ex af,af' + ld a,lp_l + ld (pan3),a + ex af,af' + jp pchD + +setrightD + ex af,af' + ld a,lp_swr + ld (panD),a + ld a,lp_r + ld (maskD),a + ex af,af' + rrca + jp fxcont + +setleftD + ex af,af' + ld a,lp_swl + ld (panD),a + ld a,lp_l + ld (maskD),a + ex af,af' + jp fxcont + +;************************************************************************************* +resetFX ;reset all fx + + ld a,(musicData) ;reset speed + ld (cspeed),a + +resetFX1 + ld a,#80 ;reset phase shift + ld (phaseshift2),a + ld (phaseshift3),a + +resetFX2 + ld a,lp_sw ;reset panning switches + ld (pan1),a + ld (panD),a + + ld a,lp_on + ld (pan2),a + ld (pan3),a + + ld a,lp_off ;TEST + ld (mask1),a + ld (maskD),a + +resetFX3 + ld a,#c6 ;reset ch1 fx + ld (fxswap1),a + ;ld (fxswap2),a + + ld (pwmswitch),a ;reset pwm sweep + + ld a,#7c ;reset volume shift drums/ch1 + ld (volswap1),a + ;inc a + ;ld (volswap2),a + + ld a,#03 ;reset drum counter mode + ld (drumswap),a + + xor a + ld (pitchslide),a + ld (pitchslide+1),a + ld (drumswap2),a ;reset drum value mode + + ret ;must return with Z-flag set +;************************************************************************************* +lpInvalidErr ;handle error caused by invalid loop point created by deleting row to loop to in livemode + pop hl ;clean stack + ld a,4 + jp errorHand + +;************************************************************************************* +IF ((HIGH($))<(HIGH($+32))) + org 256*(1+(HIGH($))) ;align to next page if necessary +.WARNING sample table crosses page boundary +ENDIF + ;ds #20 + + ds 2 ;needed for sample LUT offset calculation + +samples ;sample table may not cross page boundary + dw kickdr ;1 kick +IF MODEL = TI82 || MODEL = TI8P + dw 0 ;2 snare/hat + dw #569b ;3 metallic snare + low end + dw #3c0 ;4 short low noise/snare + dw #6aa3 ;5 "plick" + dw #5b24 ;6 periodic noise + dw #6ba4 ;7 short clap/click + dw #6940 ;8 periodic noise/snare + dw #67a0 ;9 ???! + dw #800 ;a double shot + dw #5e31 ;b tiny kick +ENDIF +IF MODEL = TI83 + dw 8 ;2 snare/hat + dw #355 ;dw #569b ;3 metallic snare + low end + dw #4ca ;4 short low noise/snare + dw #491 ;dw #6aa3 ;5 "plick" + dw #19a2 ;dw #5b24 ;6 periodic noise + dw #20af ;dw #6ba4 ;7 short clap/click + dw #2361 ;dw #6940 ;8 periodic noise/snare + dw #25a6 ;dw #67a0 ;9 ???! + dw #2a40 ;dw #800 ;a double shot + dw #2bae ;dw #5e31 ;b tiny kick +ENDIF +IF MODEL = TI8X + dw #6e ;2 snare/hat + dw #12d1 ;dw #569b ;3 metallic snare + low end + dw #5fa ;dw #3c0 ;4 short low noise/snare + dw #13c0 ;dw #6aa3 ;5 "plick" + dw #154a ;dw #5b24 ;6 periodic noise + dw #16ad ;dw #6ba4 ;7 short clap/click + dw #2c60 ;TODO dw #19b2 ;dw #6940 ;8 periodic noise/snare + dw #17a9 ;dw #67a0 ;9 ???! + dw #1d3f ;dw #800 ;a double shot + dw #1f73 ;dw #5e31 ;b tiny kick +ENDIF + dw CsrTab ;c tiny laser + dw CsrTab2 ;d noise (better) + dw fxptn00+(32*32) ;e user defined sample +usrdrum + dw 0 ;f user defined pointer + + ;dw #300 ;3 heavy snare -- this one probably goes + ;dw initSCR + ;dw #54d2 ;d noise + ;dw #4e28 ;e noise + ;dw #5fcd + +;IF ((HIGH(samples-2))<(HIGH(usrdrum+2))) +;.ERROR sample table crosses page boundary +;ENDIF + +kickdr + db #80, #80, #70, #70, #60, #60, #50, #50, #40, #40, #40, #30, #30, #30, #30 + db #20, #20, #20, #20, #20, #10, #10, #10, #10, #10, #10, #8, #8, #8, #8, #8, #8, #8 + db #4, #4, #4, #4, #4, #4, #4, #4, #2, #2, #2, #2, #2, #2, #2, #2, #2, #0 + +musicData ;the music data + include "music.asm" diff --git a/README.md b/README.md index a0a935d..28e2f30 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,31 @@ # HoustonTracker2 A music editor for TI graphing calculators + + +###About + +HoustonTracker 2 is a software sequencer that enables you to create music on Texas Instruments graphing calculators. It uses the machines' communication port to output multi-channel 1-bit music. Its interface is inspired by popular trackers such as LSDJ, Famitracker, and Milkytracker. + +HT2 supports several models of the Z80-based line of TI calculators. It is mainly targetted at older, obsolete models like the TI-82, but also works on TI-83, +TI-83Plus/SE, and TI-84Plus/SE. + +More information and online documentation can be found at +http://irrlichtproject.de/houston + + +###Features + +* 3 tone channels +* 1 non-interrupting drum channel +* up to 128 note patterns +* up to 64 drum/fx patterns +* sequence length up to 255 pattern rows +* 16-bit frequency precision +* 8-bit speed precision, can be configured per step +* various effects, including: + * L/C/R stereo hard-panning for tone and drum channels + * 8bit duty cycle control + * duty cycle sweep +* 2 user definable samples +* up to 8 savestates +* edit during playback diff --git a/_bin/bin8x b/_bin/bin8x new file mode 100755 index 0000000..d0a016c Binary files /dev/null and b/_bin/bin8x differ diff --git a/_include/doorscs.h b/_include/doorscs.h new file mode 100644 index 0000000..e69de29 diff --git a/_include/old/8xp.inc b/_include/old/8xp.inc new file mode 100644 index 0000000..9a54dec --- /dev/null +++ b/_include/old/8xp.inc @@ -0,0 +1,346 @@ +; The Ion Include File by Dan Englender + +;----> Safe Memory Areas +; saferam1 = 768 bytes (apdram) +; saferam2 = 531 bytes (statram) +; saferam3 = 128 bytes (textmem) +; saferam4 = 66 bytes (ops) +; saferam5 = 10 bytes (imathptrs) + +LPON EQU $03 +LPOFF EQU $00 +LPL EQU $01 +LPR EQU $02 +LPSW EQU $03 +LPSWL EQU $02 +LMSK EQU $0303 +LRMASK EQU #0102 ;link port stereo mask +LPSWR EQU $01 +LPORT EQU 0 +KPORT EQU 1 + +progstart EQU #9D95 + + org progstart-2 + db $BB,$6D + xor a + jr nc,begin + ret + +MACRO bcall,addr + rst #28 + dw addr +ENDM +MACRO bcallz,addr + jr nz,$+5 + rst #28 + dw addr +ENDM +MACRO bcallnz,addr + jr z,$+5 + rst #28 + dw addr +ENDM +MACRO bcallc,addr + jr nc,$+5 + rst #28 + dw addr +ENDM +MACRO bcallnc,addr + jr c,$+5 + rst #28 + dw addr +ENDM +MACRO bjump,addr + call #50 + dw addr +ENDM +; .addinstr BCALL * EF 3 NOP 1 +appBackupScreen EQU #9872 ; 768 bytes +_ldhlind EQU #4009 +_htimesl EQU #4276 +_convop1 EQU #4AEF +contrast EQU #8447 +_darkline EQU #47DD +_darkpoint EQU #47F2 +_archUnarch EQU #4FD8 +_enoughRam EQU #42FD +usermemoff EQU #89EC +libstart EQU #0004 +;saferam1 EQU #86EC +saferam1 EQU #9872 +saferam2 EQU #858f +saferam3 EQU #8508 +saferam4 EQU #8478 +saferamp EQU #9872 +saferamp2 EQU #8251 +_savedisp EQU #4C7B +_homeup EQU #4558 +_newline EQU #452E +_cleargbuf EQU #4BD0 +_indicatorOn EQU #456D +_indicatorOff EQU #4570 +_copygbuf EQU #486A +_clrlcdf EQU #4540 +_cleartextshad EQU #454C +_clrscr EQU #4543 +_clrscrf EQU #4546 +_cline EQU #4798 +_iline EQU #47E0 +_ipoint EQU #47E3 +_ParseInp EQU #4A9B +_divhlby10 EQU #400F +_cphlde EQU #400C +_disphl EQU #4507 +_divhlbya EQU #4012 +_hltimes9 EQU #40F9 +_vputmap EQU #455E +_vputs EQU #4561 +_vputsn EQU #4564 +_putmap EQU #4501 +_puts EQU #450A +_putps EQU #4510 +_putc EQU #4504 +_getkey EQU #4972 +_getk EQU #4744 +_getcsc EQU #4018 +;_RCLY EQU #4EE0 +;_RCLX EQU #4EE8 +_memfree EQU #42E5 +_chksysvar EQU #42F1 +_findsym EQU #42F4 +;_CREATEGDB EQU #4486 +;_CREATEREAL EQU #4452 +;_CREATESTRNG EQU #4472 +_createprog EQU #4339 +_createprotprog EQU #4E6D +_delvar EQU #4351 +_insertmem EQU #42F7 +_deletemem EQU #4357 +_lcdbusy EQU #4051 +op1 EQU #8478 +op2 EQU #8483 +op3 EQU #8499 +op4 EQU #8499 +op5 EQU #84A4 +op6 EQU #84AF +imathptr1 EQU #84D3 +imathptr2 EQU #84D5 +imathptr3 EQU #84D7 +imathptr4 EQU #84D9 +imathptr5 EQU #84DB +progptr EQU #9830 +cmdshad EQU #966E +plotsscreen EQU #9340 +symtable EQU #FE6E +currow EQU #844B +curcol EQU #844C +pencol EQU #86D7 +penrow EQU #86D8 +curgy EQU #8D18 +curgx EQU #8D19 +_PushRealO1 EQU #43BA +_PushRealO2 EQU #43B7 +_PushRealO3 EQU #43B4 +_PushRealO4 EQU #43B1 +_PushRealO5 EQU #43AE +_PushRealO6 EQU #43AB +_FPAdd EQU #4072 +_FPDiv EQU #4099 +_FPMult EQU #4084 +_OP1ExOP4 EQU #421C +_OP1Set0 EQU #41BF +_OP3SET2 EQU #41A4 +_PopRealO1 EQU #4390 +_PopRealO2 EQU #438D +_PopRealO3 EQU #438A +_PopRealO4 EQU #4387 +_PopRealO5 EQU #4384 +_PopRealO6 EQU #4381 +_op5exop6 EQU #420A +_op5set0 EQU #41B3 +_cpop1op2 EQU #4111 +_op3toop4 EQU #4114 +_op1toop4 EQU #4117 +_op2toop4 EQU #411A +_op4toop2 EQU #411D +_op3toop2 EQU #4120 +_op1toop3 EQU #4123 +_op5toop2 EQU #4126 +_op5toop6 EQU #4129 +_op5toop4 EQU #412C +_op1toop2 EQU #412F +_op6toop2 EQU #4132 +_op6toop1 EQU #4135 +_op4toop1 EQU #4138 +_op5toop1 EQU #413B +_op3toop1 EQU #413E +_op6toop5 EQU #4141 +_op4toop5 EQU #4144 +_op3toop5 EQU #4147 +_op2toop5 EQU #414A +_op2toop6 EQU #414D +_op1toop6 EQU #4150 +_op1toop5 EQU #4153 +_op2toop1 EQU #4156 +_op2toop3 EQU #416E +_op4toop3 EQU #4171 +_op5toop3 EQU #4174 +_op4toop6 EQU #4177 +_OP1Set1 EQU #419B +_OP1Set2 EQU #41A7 +_OP1Set3 EQU #41A1 +_OP1Set4 EQU #419E +_pushop1 EQU #43C9 +_popop1 EQU #437E +_arc_unarc EQU #4FD8 +_sin EQU #40BD +_zeroop1 EQU #41C5 +_zeroop2 EQU #41C8 +_zeroop3 EQU #41CB +_setxxop1 EQU #478C +_setxxop2 EQU #478F +_setxxxxop2 EQU #4792 +_dispop1a EQU #4BF7 +_mov9toop1 EQU #417A +_delvararc EQU #4fC6 +ptemp EQU #982E + +grbuf EQU plotsscreen +graph_mem EQU plotsscreen +gbuf EQU plotsscreen +sram EQU saferam1 +apdram EQU saferam1 +statram EQU saferam2 +statvars EQU saferam2 +vat EQU progptr +saferam5 EQU imathptr1 +_grbufcpy EQU #486A +_grbufclr EQU #4BD0 +_clrlcdfull EQU #4540 +_clrscrnfull EQU #4546 +_chkfindsym EQU #42F1 +textshadow EQU saferam3 +savesscreen EQU saferam1 +;-----> Ion Functions +lVectors EQU cmdshad+80 +ionVersion EQU lVectors +ionRandom EQU lVectors+3 +ionPutSprite EQU lVectors+6 +ionLargeSprite EQU lVectors+9 +ionGetPixel EQU lVectors+12 +ionFastCopy EQU lVectors+15 +ionDetect EQU lVectors+18 +ionDecompress EQU lVectors+21 + + +trigflags EQU 0 ; IY OFFSET VALUE +trigdeg EQU 2 +; +plotflags EQU 2 ; IY OFFSET VALUE +plotloc EQU 1 +plotdisp EQU 2 +; +grfmodeflags EQU 2 ; IY OFFSET VALUE +grffuncm EQU 4 +grfpolarm EQU 5 +grfparamm EQU 6 +grfrecurm EQU 7 +; +graphflags EQU 3 ; IY OFFSET VALUE +graphdraw EQU 0 +graphcursor EQU 2 +; +grfdbflags EQU 4 ; IY OFFSET VALUE +grfdot EQU 0 +grfsimul EQU 1 +grfgrid EQU 2 +grfpolar EQU 3 +grfnocoord EQU 4 +grfnoaxis EQU 5 +grflabel EQU 6 +; +textflags EQU 5 ; IY OFFSET VALUE +textEraseBelow EQU 1 +textScrolled EQU 2 +textInverse EQU 3 +; +onflags EQU 9 ; IY OFFSET VALUE +onRunning EQU 3 +onInterrupt EQU 4 +; +statflags EQU 9 ; IY OFFSET VALUE +statsvalid EQU 6 +; +fmtflags EQU 10 ; IY OFFSET VALUE +fmtExponent EQU 0 +fmtEng EQU 1 +; +nummode EQU 10 ; IY OFFSET VALUE +FMTREAL EQU 5 +FMTRECT EQU 6 +FMTPOLAR EQU 7 +; +curflags EQU 12 ; IY OFFSET VALUE +curAble EQU 2 +curOn EQU 3 +curLock EQU 4 +; +appflags EQU 13 ; IY OFFSET VALUE +appTextSave EQU 1 +appAutoScroll EQU 2 +; +PLOTFLAG2 EQU 17 ; IY OFFSET VALUE +EXPR_PARAM EQU 3 +EXPR_WRITING EQU 4 +; +indicflags EQU 18 ; IY OFFSET VALUE +indicRun EQU 0 +indicOnly EQU 2 +; +shiftflags EQU 18 ; IY OFFSET VALUE +shift2nd EQU 3 +shiftAlpha EQU 4 +shiftALock EQU 6 +; +tblflags EQU 19 ; IY OFFSET VALUE +AutoFill EQU 4 +AutoCalc EQU 5 +; +sgrflags EQU 20 ; IY OFFSET VALUE +grfSplit EQU 0 +VertSplit EQU 1 +WRITE_ON_GRAPH EQU 4 +textwrite EQU 7 +; +asm_flag1 EQU 33 ; IY OFFSET VALUE +asm_flag1_0 EQU 0 +asm_flag1_1 EQU 1 +asm_flag1_2 EQU 2 +asm_flag1_3 EQU 3 +asm_flag1_4 EQU 4 +asm_flag1_5 EQU 5 +asm_flag1_6 EQU 6 +asm_flag1_7 EQU 7 +; +asm_flag2 EQU 34 ; IY OFFSET VALUE +asm_flag2_0 EQU 0 +asm_flag2_1 EQU 1 +asm_flag2_2 EQU 2 +asm_flag2_3 EQU 3 +asm_flag2_4 EQU 4 +asm_flag2_5 EQU 5 +asm_flag2_6 EQU 6 +asm_flag2_7 EQU 7 +; +asm_flag3 EQU 35 ; IY OFFSET VALUE +asm_flag3_0 EQU 0 +asm_flag3_1 EQU 1 +asm_flag3_2 EQU 2 +asm_flag3_3 EQU 3 +asm_flag3_4 EQU 4 +asm_flag3_5 EQU 5 +asm_flag3_6 EQU 6 +asm_flag3_7 EQU 7 + + diff --git a/_include/old/crash82.inc b/_include/old/crash82.inc new file mode 100644 index 0000000..9ab04a0 --- /dev/null +++ b/_include/old/crash82.inc @@ -0,0 +1,368 @@ +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; CRASH82.INC for CrASH v1.1 +; made by Hideaki Omuro and Jeff Mears +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + + + +LPON EQU $fc ;link port off +LPOFF EQU $c0 ;link port on +LPL EQU $d4 ;link port left on +LPR EQU $e8 ;link port right on +LPSW EQU $3c ;toggle link port state +LPSWL EQU %00101000 ;toggle link port state left +LPSWR EQU %00010100 ;toggle link port state right +LMSK EQU $fcfc ;link port mask +LRMASK EQU $d4e8 ;link port stereo mask +LPORT EQU 0 +KPORT EQU 1 + +progstart EQU #9104 + + org progstart + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; RAM Locations +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +;Name Address Len Meaning +;ÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄ ÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +KEY_0 EQU $8000 ;Byte Scancode of last key, 0 if gotten +KEY_1 EQU $8001 ;Byte Scancode of key down now +KEY_2 EQU $8002 ;Byte Same as $8001, $FF if more than one key is down +KEY_STAT EQU $8004 ;Byte Bit 2 set EQU key down now +LAST_KEY EQU $8006 ;Byte Last key pressed +CONTRAST EQU $8008 ;Byte Contrast ($00 to $1F) +CURSOR_POS EQU $800C ;Word Text position for word operations +CURSOR_ROW EQU $800C ;Byte Text cursor row +CURSOR_COL EQU $800D ;Byte Text cursor column +BUSY_COUNTER EQU $8026 ;Byte Counter for busy indicator +BUSY_BITMAP EQU $8027 ;Byte Bitmap for busy indicator +op1 EQU $8028 ; 11 OP1 +OP2 EQU $8033 ; 11 OP2 +OP3 EQU $803E ; 11 OP3 +OP4 EQU $8049 ; 11 OP4 +OP5 EQU $8054 ; 11 OP5 +OP6 EQU $805F ; 11 OP6 +TEXT_MEM EQU $808F ; 128 text memory +GRAF_CURS EQU $8215 ;Word Cursor position for graphics +CURSOR_X EQU $8215 ;Byte X value of graphics cursor +CURSOR_Y EQU $8216 ;Byte Y value of graphics cursor +APD_BUF EQU $8228 ; 768 APD screen buffer +_IY_TABLE EQU $8528 ; N/A Where IY usually points +GRAPH_MEM EQU $88B8 ; 768 Graphics Buffer +TEXT_MEM2 EQU $8BDF ; 128 Secondary text memory +WIN_START EQU $8C8F ;Byte Number of first row in window +WIN_END EQU $8C90 ;Byte Number of last row in window +CRASH_VER EQU $8D73 ;Byte Version number of CrASH +VAT_START EQU $FE6E ; N/A Start of VAT + +; The following will be used in programs using the APD buffer. If something +; important (ie. interrupt) is going on inside APD_BUF, INT_STATE will not +; be 00. (Look in CrASHprg.TXT for details) +APD_FREE EQU $8D70 ;Word Public Free Mem of APD_BUF ($000EQUnone, otherEQUusing) +INT_STATE EQU $8D72 ;Byte Public Stat of Interrupts (00EQUnone, otherEQUusing) + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; Variable Regions +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; You can allocate memory freely in FREE_A regions. +; You must be careful to not use FREE_B if your program calls CR_KHAND + +;Free Memory Regions Len Comments +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +FREE_A1 EQU GRAPH_MEM ;768 Cleared when starting a program +FREE_A2 EQU TEXT_MEM ;128 Cleared when starting a program +FREE_A3 EQU op1 ; 66 Can be used if only using normal ROM_CALLs +FREE_B EQU TEXT_MEM2 ;128 Cleared after calling CR_KHAND +FREE_C EQU APD_BUF ;768 If INT_STATE is not 0, check for available APD_FREE + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; CrASH call Addresses (use CALL) +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; This is a list of useful functions created by the authors of CrASH. They +; are embedded into CrASH, and are very useful tools. + +; Use CALL to call these functions. + +EXIT_2_TIOS EQU $8D88 ; Exits to TI-OS with a clear screen. (can use JP) +RAND EQU $8D8B ; Returns a random number 0-127 in A. +CP_HL_BC EQU $8D8E ; Compares HL and BC, like CP_HL_DE +CR_KHAND EQU $8D91 ; Key_Hand; does not crash if turned off +CR_GRBCopy EQU $8D94 ; Fast copy to LCD - Read below + +; CR_GRBCopy is limited: +; May not work correctly if LCD_Port is set to go auto right +; May not work correctly if calc is turboed +; Only copies from GRAPH_MEM +; Still testing - please report bugs while using it. + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ROM Addresses (use CALL) +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; This is a list of useful functions inside the TI-82's ROM. + +; Use CALL to call these functions. + +;AddressName Address Registers Description +;ÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +LD_HL_MHL EQU $0033 ;HLA HL EQU (HL), A EQU L +CP_HL_DE EQU $0095 ;F CP HL, DE +UNPACK_HL EQU $00A1 ;HLA HL EQU int(HL/10), A EQU HL MOD 10 +DIV_HL_A EQU $00A3 ;HLA HL EQU int(HL/A), A EQU HL MOD A +KEY_READ EQU $01B8 ;AB Does raw keyboard read with mask A; returns A +STORE_KEY EQU $01C7 ;? Store keystroke from A +GET_KEY EQU $01D4 ;HL? Get immediate keystroke into A +DISP_DELAY EQU $07F3 ; Delay for display controller (60 clocks) +FIND_PIXEL EQU $4166 ;? Find pixel (rom page must be 4) + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ROM Offset Addresses (use ROM_CALL) +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; To use functions not included here just make a definition like the ones +; below in your program (not recommended). If you are using the addresses +; in rom found by another source for rom version 19, remember to subtract $1A +; from that address. (The ones listed are roms version 16-18) + +; Use ROM_CALL to call these functions. + +;#DEFINE ROM_CALLaddr) CALL $8D74 \ .DW addr + +MACRO ROM_CALL,addr + call #8d74 + dw addr +ENDM + +TR_CHARPUT EQU $3738 ; Raw display of A on screen, normal text style +TX_CHARPUT EQU $39D2 ; Xlated display of A on screen, normal text style +D_ZT_STR EQU $38FA ; Display zero-terminated normal text string +D_LT_STR EQU $373E ; Display length-byte normal text string +D_HL_DECI EQU $387C ; Disp HL as 5-char, right just., blank-pad. integer +LAST_LINE EQU $3774 ; Is it the last line? +NEXT_LINE EQU $377A ; Goto next line (might scroll) +SCROLL_UP EQU $3786 ; Scroll text screen up +UP_TEXT EQU $37F2 ; Update text mem from command shadow + +M_CHARPUT EQU $37CE ; Display %A on screen, menu style +D_ZM_STR EQU $37D4 ; Display zero-terminated string, menu style +D_LM_STR EQU $37DA ; Display length indexed string, menu style + +CLEARLCD EQU $389A ; Clear LCD, but not text or graphics memory +CLEARTEXT_W EQU $37B0 ; Clear LCD and text memory, but only current window (affected by 1,(IY+13)) +CLEARTEXT_F EQU $37A4 ; Clear LCD and text memory (affected by 1,(IY+13)) +CLEAR_DISP EQU $38CA ; Clear display +BACKUP_DISP EQU $39C6 ; Copy display to APD_BUF +RESTOR_DISP EQU $38DC ; Copy APD_BUF to display + +; In OShell-82, two of these ROM functions are called by the TI-83 name which +; TI gave them. To make easier for TI-83 programmers, the following two +; definitions are included, although NOT recommended for usage AT ALL. +; ÄÄÄ ÄÄÄÄÄÄ +; Also, there are alternate CrASH calls that will do the same thing, but +; enhanced. (Look above) + +DISP_GRAPH EQU $38AC ; Display contents of GRAPH_MEM on LCD +KEY_HAND EQU $3924 ; Get key using key handler (2nd, alpha, contrast) + +_GRBUFCPY_V EQU DISP_GRAPH ; Way too slow +_GETKEY EQU KEY_HAND ; Crashes when you turn off calc. (not a joke) + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; Ports +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +P_LINK EQU $00 ; Link port (TI-85) +P_KEYBOARD EQU $01 ; Port used to access keys (TI-85) +P_ROM EQU $02 ; Rom page switching and other things +P_STATUS EQU $03 ; Used to get/set status of varius hardware +P_INT EQU $04 ; Interrupt speed (don't change!!! the display needs it) +P_LCD_CON EQU $10 ; Control port for display controller (TI-83) +P_LCD_DATA EQU $11 ; Data port for display controller (TI-83) + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; Misc +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +;#DEFINE TEXT_START RES 1,(IY+0Dh) \ RES 2,(IY+0Dh) \ ROM_CALL(CLEAR_DISP) \ LD HL,0000h \ LD (CURSOR_POS),HL +MACRO TEXT_START + res 1,(iy+#0d) + res 2,(iy+#0d) + ROM_CALL(CLEAR_DISP) + ld hl,0 + ld (CURSOR_POS),hl +ENDM +MACRO TEXT_END + set 2,(iy+#0d) + set 1,(iy+#0d) +ENDM +;#DEFINE TEXT_END SET 2,(IY+0Dh) \ SET 1,(IY+0Dh) + +G_NONE EQU $00 +G_DOWN EQU $01 +G_LEFT EQU $02 +G_RIGHT EQU $03 +G_RIGTH EQU $03 ; Included because author of ASH couldn't spell :) +G_UP EQU $04 +G_ENTER EQU $09 +G_PLUS EQU $0A +G_MINUS EQU $0B +G_TIMES EQU $0C +G_DIV EQU $0D +G_CARROT EQU $0E +G_CLEAR EQU $0F +G_NEG EQU $11 +G_3 EQU $12 +G_6 EQU $13 +G_9 EQU $14 +G_PARENR EQU $15 +G_TAN EQU $16 +G_VARS EQU $17 +G_PERIOD EQU $19 +G_2 EQU $1A +G_5 EQU $1B +G_8 EQU $1C +G_PARENL EQU $1D +G_COS EQU $1E +G_PRGM EQU $1F +G_STAT EQU $20 +G_0 EQU $21 +G_1 EQU $22 +G_4 EQU $23 +G_7 EQU $24 +G_COMMA EQU $25 +G_SIN EQU $26 +G_MATRIX EQU $27 +G_XTO EQU $28 +G_ON EQU $29 +G_STO EQU $2A +G_LN EQU $2B +G_LOG EQU $2C +G_SQR EQU $2D +G_INVE EQU $2E +G_MATH EQU $2F +G_ALPHA EQU $30 +G_GRAPH EQU $31 +G_TRACE EQU $32 +G_ZOOM EQU $33 +G_WINDOW EQU $34 +G_YEDIT EQU $35 +G_2ND EQU $36 +G_MODE EQU $37 +G_DEL EQU $38 + +K_RIGTH EQU 1 ; RIGHT RIGHT +K_RIGHT EQU 1 ; RIGHT RIGHT +K_LEFT EQU 2 ; LEFT LEFT +K_UP EQU 3 ; UP UP +K_DOWN EQU 4 ; DOWN DOWN +K_ENTER EQU 5 ; ENTER ENTER +K_CLEAR EQU 6 ; CLEAR CLEAR +K_DEL EQU 7 ; DEL DEL +K_INS EQU 8 ; DEL INS +K_RCL EQU 9 ; STO> RCL +K_ENTRY EQU 10 ; ENTER ENTRY +K_BOL EQU 11 ; LEFT BOL +K_EOL EQU 12 ; RIGHT EOL +K_PRGM EQU 45 ; PRGM PRGM +K_ZOOM EQU 46 ; ZOOM ZOOM +K_DRAW EQU 47 ; PRGM DRAW +K_PLOT EQU 48 ; YEQU STAT PLOT +K_MATH EQU 49 ; MATH MATH +K_TEST EQU 50 ; MATH TEST +K_VARS EQU 52 ; VARS VARS +K_MEM EQU 53 ; + MEM +K_MATRIX EQU 54 ; MATRIX MATRIX +K_STAT EQU 55 ; STAT STAT +K_YVARS EQU 56 ; VARS Y-VARS +K_ANGLE EQU 57 ; MATRIX ANGLE +K_LIST EQU 58 ; STAT LIST +K_CALC EQU 59 ; TRACE CALC +K_QUIT EQU 64 ; MODE QUIT +K_LINK EQU 65 ; X,T,theta LINK +K_GRAPH EQU 69 ; GRAPH GRAPH +K_MODE EQU 70 ; MODE MODE +K_WINDOW EQU 73 ; WINDOW WINDOW +K_YEDIT EQU 74 ; YEQU YEQU +K_TABLE EQU 75 ; GRAPH TABLE +K_TBLSET EQU 76 ; WINDOW TblSet +K_TRACE EQU 93 ; TRACE TRACE +K_PLUS EQU 129 ; + + +K_MINUS EQU 130 ; - - +K_TIMES EQU 131 ; * * +K_DIV EQU 132 ; / / +K_POWER EQU 133 ; ^ ^ +K_LPAREN EQU 134 ; ( ( +K_RPAREN EQU 135 ; ) ) +K_LBRACK EQU 136 ; * [ +K_RBRACK EQU 137 ; - ] +K_STO EQU 139 ; STO> STO> +K_COMMA EQU 140 ; , , +K_NEG EQU 141 ; (-) (-) +K_PERIOD EQU 142 ; . . +K_0 EQU 143 ; 0 0 +K_1 EQU 144 ; 1 1 +K_2 EQU 145 ; 2 2 +K_3 EQU 146 ; 3 3 +K_4 EQU 147 ; 4 4 +K_5 EQU 148 ; 5 5 +K_6 EQU 149 ; 6 6 +K_7 EQU 150 ; 7 7 +K_8 EQU 151 ; 8 8 +K_9 EQU 152 ; 9 9 +K_EE EQU 153 ; , EE +K_SEMI EQU 154 ; 0 ; +K_A EQU 155 ; MATH A +K_B EQU 156 ; MATRIX B +K_C EQU 157 ; PRGM C +K_D EQU 158 ; X^-1 D +K_E EQU 159 ; SIN E +K_F EQU 160 ; COS F +K_G EQU 161 ; TAN G +K_H EQU 162 ; ^ H +K_I EQU 163 ; X^2 I +K_J EQU 164 ; , J +K_K EQU 165 ; ( K +K_L EQU 166 ; ) L +K_M EQU 167 ; / M +K_N EQU 168 ; LOG N +K_O EQU 169 ; 7 O +K_P EQU 170 ; 8 P +K_Q EQU 171 ; 9 Q +K_R EQU 172 ; * R +K_S EQU 173 ; LN S +K_T EQU 174 ; 4 T +K_U EQU 175 ; 5 U +K_V EQU 176 ; 6 V +K_W EQU 177 ; - W +K_X EQU 178 ; STO> X +K_Y EQU 179 ; 1 Y +K_Z EQU 180 ; 2 Z +K_XTO EQU 181 ; X,T,theta X,T,theta +K_PI EQU 182 ; ^ Pi +K_INVERSE EQU 183 ; X^-1 X^-1 +K_SIN EQU 184 ; SIN SIN +K_ASIN EQU 185 ; SIN SIN^-1 +K_COS EQU 186 ; COS COS +K_ACOS EQU 187 ; COS COS^-1 +K_TAN EQU 188 ; TAN TAN +K_ATAN EQU 189 ; TAN TAN^-1 +K_SQR EQU 190 ; X^2 X^2 +K_SQRT EQU 191 ; X^2 SQRT +K_LN EQU 192 ; LN LN +K_EX EQU 193 ; LN e^X +K_LOG EQU 194 ; LOG LOG +K_TENP EQU 195 ; LOG 10^X +K_ANS EQU 198 ; (-) ANS +K_COLON EQU 199 ; . : +K_QUEST EQU 203 ; (-) ? +K_QUOTE EQU 204 ; + " +K_THETA EQU 205 ; 3 THETA +K_LBRACE EQU 237 ; ( { +K_RBRACE EQU 238 ; ) } +K_ABS EQU 244 ; X^-1 ABS +K_L1 EQU 245 ; 1 L1 +K_L2 EQU 246 ; 2 L2 +K_L3 EQU 247 ; 3 L3 +K_L4 EQU 248 ; 4 L4 +K_L5 EQU 249 ; 5 L5 +K_L6 EQU 250 ; 6 L6 +K_n EQU 251 ; 9 n +K_Vn1 EQU 252 ; 8 Vn-1 +K_Un1 EQU 253 ; 7 Un-1 diff --git a/_include/old/ion.inc b/_include/old/ion.inc new file mode 100644 index 0000000..ebba971 --- /dev/null +++ b/_include/old/ion.inc @@ -0,0 +1,342 @@ +; The Ion Include File by Dan Englender + +;----> Safe Memory Areas +; saferam1 = 768 bytes (apdram) +; saferam2 = 531 bytes (statram) +; saferam3 = 128 bytes (textmem) +; saferam4 = 66 bytes (ops) +; saferam5 = 10 bytes (imathptrs) + +LPON EQU $d3 +LPOFF EQU $d0 +LPL EQU $d1 +LPR EQU $d2 +LPSW EQU $03 +LPSWL EQU $02 +LMSK EQU $d3d3 +LRMASK EQU #d1d2 ;link port stereo mask +LPSWR EQU $01 +LPORT EQU 0 +KPORT EQU 1 + +MACRO bcall,addr + call addr +ENDM +MACRO bcallz,addr + call z,addr +ENDM +MACRO bcallnz,addr + call nz,addr +ENDM +MACRO bcallc,addr + call c,addr +ENDM +MACRO bcallnc,addr + call nc,addr +ENDM +MACRO bjump,addr + jp addr +ENDM + +progstart EQU #9327 + + org progstart + xor a + jr nc,begin + ret + +; .addinstr BCALL * CD 3 NOP 1 +_htimesl EQU #4382 +usermemoff EQU #8565 +libstart EQU #0002 +saferam1 EQU #8265 +saferam2 EQU #858F +saferam3 EQU #80C9 +saferam4 EQU #8039 +_savedisp EQU #4859 +_zeroop1 EQU #428E +_getcsc EQU #4014 +_homeup EQU #4775 +_newline EQU #473D +_darkline EQU #4AE0 +_indicatorOff EQU #4795 +_indicatorOn EQU #4791 +_cleargbuf EQU #515B +_copygbuf EQU #4B9C +_clrlcdf EQU #4755 +_cleartextshad EQU #4765 +_clrscr EQU #4759 +_clrscrf EQU #475D +_cline EQU #4A84 +_iline EQU #4AE4 +_ipoint EQU #4AE8 +_ldhlind EQU #4000 +_divhlby10 EQU #4008 +_cphlde EQU #4004 +_disphl EQU #4709 +_divhlbya EQU #400C +_hltimes9 EQU #4146 +_vputmap EQU #477D +_vputs EQU #4781 +_vputsn EQU #4785 +_putmap EQU #4701 +_puts EQU #470D +_putps EQU #4715 +_parseinp EQU #4E8C +_putc EQU #4705 +_getkey EQU #4CFE +_getk EQU #4A18 +_rcly EQU #4EE0 +_rclx EQU #4EE8 +_memfree EQU #441A +_chksysvar EQU #442A +_findsym EQU #442E +_creategdb EQU #4486 +_createprog EQU #448A +_createreal EQU #4452 +_createstring EQU #4472 +_delvar EQU #44AA +_insertmem EQU #4432 +_deletemem EQU #44B2 +_lcdbusy EQU #4066 +ptemp EQU #9317 +op1 EQU #8039 +op2 EQU #8044 +op3 EQU #804F +op4 EQU #805A +op5 EQU #8065 +op6 EQU #8070 +imathptr1 EQU #8094 +imathptr2 EQU #8096 +imathptr3 EQU #8098 +imathptr4 EQU #809A +imathptr5 EQU #809C +progptr EQU #9319 +cmdshad EQU #9157 +plotsscreen EQU #8E29 +symtable EQU #FE6E +currow EQU #800C +curcol EQU #800D +pencol EQU #8252 +penrow EQU #8253 +curgy EQU #886D +curgx EQU #886E +_op1toop2 EQU #418E +_op1toop3 EQU #417E +_op1toop4 EQU #416E +_op1toop5 EQU #41BE +_op1toop6 EQU #41BA +_op2toop1 EQU #41C2 +_op2toop3 EQU #41F6 +_op2toop4 EQU #4172 +_op2toop5 EQU #41B2 +_op2toop6 EQU #41B6 +_op3toop1 EQU #41A2 +_op3toop2 EQU #417A +_op3toop4 EQU #416A +_op3toop5 EQU #41AE +_op4toop1 EQU #419A +_op4toop2 EQU #4176 +_op4toop3 EQU #41FA +_op4toop5 EQU #41AA +_op4toop6 EQU #4202 +_op5toop1 EQU #419E +_op5toop2 EQU #4182 +_op5toop3 EQU #41FE +_op5toop4 EQU #418A +_op5toop6 EQU #4186 +_op6toop1 EQU #4196 +_op6toop2 EQU #4192 +_op6toop5 EQU #41A6 +_op1exop2 EQU #4306 +_op1exop3 EQU #42FE +_op1exop4 EQU #4302 +_op1exop5 EQU #42EE +_op1exop6 EQU #42F2 +_op2exop4 EQU #42F6 +_op2exop5 EQU #42FA +_op2exop6 EQU #42E6 +_op5exop6 EQU #42EA +_PUSHREALO1 EQU #4536 +_PUSHREALO4 EQU #452A +_POPREALO2 EQU #44FA +_POPREALO5 EQU #44EE +_PUSHREALO2 EQU #4532 +_PUSHREALO5 EQU #4526 +_POPREALO3 EQU #44F6 +_POPREALO6 EQU #44EA +_PUSHREALO3 EQU #452E +_PUSHREALO6 EQU #4522 +_POPREALO1 EQU #44FE +_POPREALO4 EQU #44F2 +_FPMULT EQU #40AA +_FPADD EQU #4092 +_OP1SET0 EQU #4286 +_SIN EQU #40F6 +_op1set1 EQU #4232 +_op1set2 EQU #4242 +_op1set3 EQU #423A +_op1set4 EQU #4236 +_op2set0 EQU #4282 +_op2set1 EQU #4252 +_op2set2 EQU #4246 +_op2set3 EQU #422E +_op2set4 EQU #422A +_op2set5 EQU #4222 +_op2set8 EQU #421E +_op2set60 EQU #4EA8 +_op2setA EQU #4226 +_op3set0 EQU #427E +_op3set1 EQU #421A +_op3set2 EQU #423E +_op4set0 EQU #427A +_op4set1 EQU #4216 +_op5set0 EQU #4276 +_pushop1 EQU #454A +_pushop3 EQU #4542 +_popop1 EQU #44E6 +_popop3 EQU #44E2 +_setxxop1 EQU #4A74 +_setxxop2 EQU #4A78 +_setxxxxop2 EQU #4A7C +_dispop1a EQU #51D4 +_mov9toop1 EQU #4206 +contrast EQU #8008 + + +grbuf EQU plotsscreen +graph_mem EQU plotsscreen +gbuf EQU plotsscreen +sram EQU saferam1 +apdram EQU saferam1 +statram EQU saferam2 +statvars EQU saferam2 +vat EQU progptr +saferam5 EQU imathptr1 +_grbufcpy EQU #4B9C +_grbufclr EQU #515B +_clrlcdfull EQU #4755 +_clrscrnfull EQU #475D +_chkfindsym EQU #442A +textshadow EQU saferam3 +savesscreen EQU saferam1 +;-----> Ion Functions +lVectors EQU cmdshad+80 +ionVersion EQU lVectors +ionRandom EQU lVectors+3 +ionPutSprite EQU lVectors+6 +ionLargeSprite EQU lVectors+9 +ionGetPixel EQU lVectors+12 +ionFastCopy EQU lVectors+15 +ionDetect EQU lVectors+18 +ionDecompress EQU lVectors+21 + + +trigflags EQU 0 ; IY OFFSET VALUE +trigdeg EQU 2 +; +plotflags EQU 2 ; IY OFFSET VALUE +plotloc EQU 1 +plotdisp EQU 2 +; +grfmodeflags EQU 2 ; IY OFFSET VALUE +grffuncm EQU 4 +grfpolarm EQU 5 +grfparamm EQU 6 +grfrecurm EQU 7 +; +graphflags EQU 3 ; IY OFFSET VALUE +graphdraw EQU 0 +graphcursor EQU 2 +; +grfdbflags EQU 4 ; IY OFFSET VALUE +grfdot EQU 0 +grfsimul EQU 1 +grfgrid EQU 2 +grfpolar EQU 3 +grfnocoord EQU 4 +grfnoaxis EQU 5 +grflabel EQU 6 +; +textflags EQU 5 ; IY OFFSET VALUE +textEraseBelow EQU 1 +textScrolled EQU 2 +textInverse EQU 3 +; +onflags EQU 9 ; IY OFFSET VALUE +onRunning EQU 3 +onInterrupt EQU 4 +; +statflags EQU 9 ; IY OFFSET VALUE +statsvalid EQU 6 +; +fmtflags EQU 10 ; IY OFFSET VALUE +fmtExponent EQU 0 +fmtEng EQU 1 +; +nummode EQU 10 ; IY OFFSET VALUE +FMTREAL EQU 5 +FMTRECT EQU 6 +FMTPOLAR EQU 7 +; +curflags EQU 12 ; IY OFFSET VALUE +curAble EQU 2 +curOn EQU 3 +curLock EQU 4 +; +appflags EQU 13 ; IY OFFSET VALUE +appTextSave EQU 1 +appAutoScroll EQU 2 +; +PLOTFLAG2 EQU 17 ; IY OFFSET VALUE +EXPR_PARAM EQU 3 +EXPR_WRITING EQU 4 +; +indicflags EQU 18 ; IY OFFSET VALUE +indicRun EQU 0 +indicOnly EQU 2 +; +shiftflags EQU 18 ; IY OFFSET VALUE +shift2nd EQU 3 +shiftAlpha EQU 4 +shiftALock EQU 6 +; +tblflags EQU 19 ; IY OFFSET VALUE +AutoFill EQU 4 +AutoCalc EQU 5 +; +sgrflags EQU 20 ; IY OFFSET VALUE +grfSplit EQU 0 +VertSplit EQU 1 +WRITE_ON_GRAPH EQU 4 +textwrite EQU 7 +; +asm_flag1 EQU 33 ; IY OFFSET VALUE +asm_flag1_0 EQU 0 +asm_flag1_1 EQU 1 +asm_flag1_2 EQU 2 +asm_flag1_3 EQU 3 +asm_flag1_4 EQU 4 +asm_flag1_5 EQU 5 +asm_flag1_6 EQU 6 +asm_flag1_7 EQU 7 +; +asm_flag2 EQU 34 ; IY OFFSET VALUE +asm_flag2_0 EQU 0 +asm_flag2_1 EQU 1 +asm_flag2_2 EQU 2 +asm_flag2_3 EQU 3 +asm_flag2_4 EQU 4 +asm_flag2_5 EQU 5 +asm_flag2_6 EQU 6 +asm_flag2_7 EQU 7 +; +asm_flag3 EQU 35 ; IY OFFSET VALUE +asm_flag3_0 EQU 0 +asm_flag3_1 EQU 1 +asm_flag3_2 EQU 2 +asm_flag3_3 EQU 3 +asm_flag3_4 EQU 4 +asm_flag3_5 EQU 5 +asm_flag3_6 EQU 6 +asm_flag3_7 EQU 7 diff --git a/_include/old/mallard.inc b/_include/old/mallard.inc new file mode 100644 index 0000000..dbb6da0 --- /dev/null +++ b/_include/old/mallard.inc @@ -0,0 +1,3225 @@ +; Mallard include file +; (C) 2005, by Michael Vincent. All rights reserved. + +LPON EQU #03 +LPOFF EQU #00 +LPL EQU #01 +LPR EQU #02 +LPSW EQU #03 +LPSWL EQU #02 +LMSK EQU #0303 +LRMASK EQU #0102 ;link port stereo mask +LPSWR EQU #01 +LPORT EQU 0 +KPORT EQU 1 + +userMem equ #9c37 + + org userMem + db $D9,$00,"Duck" + dw begin + + +;See end of file for shell equates + +; +;MACROS +;======================== + +MACRO bcall,addr + rst #28 + dw addr +ENDM +MACRO bcallz,addr + jr nz,$+5 + rst #28 + dw addr +ENDM +MACRO bcallnz,addr + jr z,$+5 + rst #28 + dw addr +ENDM +MACRO bcallc,addr + jr nc,$+5 + rst #28 + dw addr +ENDM +MACRO bcallnc,addr + jr c,$+5 + rst #28 + dw addr +ENDM +MACRO bjump,addr + call #50 + dw addr +ENDM +MACRO AppOnErr,addr + ld hl,addr + call APP_PUSH_ERRORH +ENDM +MACRO AppOffErr + call APP_POP_ERRORH +ENDM + + +;====================================================================== +; Include File for the TI-73 +; Last Updated 3/14/2005 (HAPPY PI DAY!) +; +; A few revisions and additional B_CALLs by Michael Vincent. +; +; Copyright (c) 2002 Texas Instruments: The Licensed Materials are +; copyrighted by TI. LICENSEE agrees that it will +; not delete the copyright notice, trademarks or +; protective notices from any copy made by LICENSEE. +; +; Warranty: TI does not warrant that the Licensed Materials will +; be free from errors or will meet your specific requirements. +; The Licensed Materials are made available "AS IS" to LICENSEE. +; +; Limitations: TI MAKES NO WARRANTY OR CONDITION, EITHER EXPRESS +; OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, +; REGARDING THE LICENSED MATERIALS. IN NO EVENT SHALL +; TI OR ITS SUPPLIERS BE LIABLE FOR ANY INDIRECT, INCIDENTAL +; OR CONSEQUENTIAL DAMAGES, LOSS OF PROFITS, LOSS OF USE OR DATA, +; OR INTERRUPTION OF BUSINESS, WHETHER THE ALLEGED DAMAGES ARE +; LABELED IN TORT, CONTRACT OR INDEMNITY. +; +;======================================================================== + + +;SYMBOLIC_DEBUG_START +;================================= +;entry points +;================================= +_AbsO1O2Cp equ #40f0 +_AbsO1PAbsO2 equ #405a +_ACos equ #40d2 +_ACosRad equ #40c6 +_AdrLEle equ #4ab6 +_AdrMRow equ #4567 +_AdrMEle equ #456a +_AllEq equ #4792 +_AllocFPS equ #4369 +_AllocFPS1 equ #436c +_AnsName equ #4B67 +_ApdSetup equ #4c06 +_AppGetCbl equ #4b97 +_AppGetCalc equ #4b9a +_AppInit equ #4048 +_ASin equ #40d8 +_ASinRad equ #40cf +_ATanRad equ #40c9 +_ATan2Rad equ #40cc +_ATan equ #40d5 +_ATan2 equ #40db + +_BinOPExec equ #459a +_BufClear equ #4840 + +_CanAlphIns equ #4ab0 +_ChkFindSym equ #42d9 +_CircCmd equ #46f6 +_CkInt equ #423a +_CkOdd equ #423d +_CkOP1C0 equ #422b +_CkOP1FP0 equ #422e +_CkOP1Pos equ #4252 +_CkOP1Real equ #40e7 +_CkOP2FP0 equ #4231 +_CkOP2Pos equ #424f +_CkOP2Real equ #42ca +_CkPosInt equ #4237 +_CkValidNum equ #426a +_CleanAll equ #4927 +_ClearRect equ #4cfc +_ClearRow equ #4c8d +_CLine equ #46cc +_CLineS equ #46cf +_CloseEditBuf equ #47E9 +_CloseEditBufNoR equ #46a2 +_CloseEditEqu equ #4867 +_CloseProg equ #490c +_ClrGraphRef equ #490f +_ClrLCD equ #44aa +_ClrLCDFull equ #44a7 +_ClrLp equ #41E3 +_ClrOP1S equ #4258 +_ClrOP2S equ #4255 +_ClrScrn equ #44b0 +_ClrScrnFull equ #44ad +_ClrTxtShd equ #44b3 +_CmpSyms equ #4921 +_ConvDim equ #4B58 +_ConvDim00 equ #4B5B +_ConvOP1 equ #49ab +_Cos equ #40c0 +_CpHLDE equ #4003 +_CPoint equ #4d89 +_CPointS equ #4717 +_CpOP1OP2 equ #40f3 +_CpOP4OP3 equ #40ea +_CpyO1toFPS1 equ #4411 +_CpyO1toFPS2 equ #4420 +_CpyO1toFPS3 equ #442c +_CpyO1toFPS4 equ #443e +_CpyO1toFPS5 equ #4438 +_CpyO1toFPS6 equ #4432 +_CpyO1toFPS7 equ #4435 +_CpyO1toFPST equ #43ff +_CpyO2toFPS1 equ #440e +_CpyO2toFPS2 equ #4417 +_CpyO2toFPS3 equ #4429 +_CpyO2toFPS4 equ #443b +_CpyO2toFPST equ #43f9 +_CpyO3toFPS1 equ #4408 +_CpyO3toFPS2 equ #441a +_CpyO3toFPST equ #43f6 +_CpyO5toFPS1 equ #440b +_CpyO5toFPS3 equ #4426 +_CpyO6toFPS2 equ #441d +_CpyO6toFPST equ #43fc +_CpyStack equ #43de +_Cpyto1FPS1 equ #43e7 +_Cpyto1FPS10 equ #43a8 +_Cpyto1FPS11 equ #438d +_Cpyto1FPS2 equ #43f0 +_Cpyto1FPS3 equ #43bd +_Cpyto1FPS4 equ #43c3 +_Cpyto1FPS5 equ #4393 +_Cpyto1FPS6 equ #4399 +_Cpyto1FPS7 equ #439f +_Cpyto1FPS8 equ #43a2 +_Cpyto1FPS9 equ #43ab +_Cpyto1FPST equ #43d8 +_CpyTo2FPS1 equ #43e4 +_CpyTo2FPS2 equ #43ed +_CpyTo2FPS3 equ #43b7 +_CpyTo2FPS4 equ #43ae +_CpyTo2FPS5 equ #4390 +_CpyTo2FPS6 equ #4396 +_CpyTo2FPS7 equ #439c +_CpyTo2FPS8 equ #43a5 +_CpyTo2FPST equ #43D5 +_CpyTo3FPS1 equ #43e1 +_CpyTo3FPS2 equ #43c6 +_CpyTo3FPST equ #43d2 +_CpyTo4FPST equ #43cf +_CpyTo5FPST equ #43c9 +_CpyTo6FPST equ #43cc +_CpyTo6FPS3 equ #43b1 +_CpyTo6FPS2 equ #43b4 +_CpyToFPS1 equ #4414 +_CpyToFPS2 equ #4423 +_CpyToFPS3 equ #442f +_CpyToFPST equ #4402 +_CpyToStack equ #4405 +_Create0Equ equ #4303 +_CreateAppVar equ #4312 +_CreateEqu equ #4309 +_CreatePict equ #430c +_CreateProg equ #430f +_CreateReal equ #42f4 +_CreateRList equ #42fa +_CreateStrng equ #4300 +_Cube equ #407b +_CursorOff equ #4522 +_CursorOn equ #4528 + +_DarkLine equ #46ff +_DarkPnt equ #4714 +_DataSize equ #433c +_DataSizeA equ #4339 +_DeallocFPS equ #4363 +_DeallocFPS1 equ #4366 +_DecO1Exp equ #4261 +_DelListEl equ #4906 +_DelMem equ #4330 +_DelRes equ #48fa +_DelVar equ #432a +_DisableApd equ #4be8 +_DisableAPI equ #4bdf +_DispDone equ #4519 +_DispEOL equ #450a +_DispHL equ #446e +_DisplayImage equ #4d5c +_DispOP1A equ #4AFB +_DivHLBy10 equ #4006 +_DivHLByA equ #4009 +_DrawCirc2 equ #4aad +_DrawCmd equ #47dd +_DrawRectBorder equ #4d2c +_DrawRectBorderClear equ #4d3b +_DrwRctBorderClr equ #4d3b +_DToR equ #4075 + +_EditProg equ #4909 +_EnableApd equ #4beb +_EnoughMem equ #42e5 +_EOP1NotReal equ #4273 +_Equ_or_NewEqu equ #42af +_EraseEOL equ #44b9 +_EraseRectBorder equ #4d35 +_ErrArgument equ #49ff +_ErrBadGuess equ #4a2f +_ErrBreak equ #4a20 +_ErrD_OP1_0 equ #42be +_ErrD_OP1_LE_0 equ #42bb +_ErrD_OP1Not_R equ #42b5 +_ErrD_OP1NotPos equ #42b2 +_ErrD_OP1NotPosInt equ #42b8 +_ErrDataType equ #49f9 +_ErrDimMismatch equ #4a02 +_ErrDimension equ #4a05 +_ErrDivBy0 equ #49e4 +_ErrDomain equ #49e7 +_ErrIncrement equ #49ea +_ErrInvalid equ #4a11 +_ErrIterations equ #4a2c +_ErrLinkXmit equ #4a38 +_ErrMemory equ #4a0b +_ErrNon_Real equ #49ed +_ErrNonReal equ #495a +_ErrNotEnoughMem equ #4441 +_ErrOverflow equ #49e1 +_ErrSignChange equ #4a29 +_ErrStat equ #4a23 +_ErrStatPlot equ #4a35 +_ErrSyntax equ #49f0 +_ErrTolTooSmall equ #4a32 +_ErrUndefined equ #4a08 +_EToX equ #40b4 +_ExLp equ #4228 +_ExpToHex equ #4249 + +_FillRect equ #4d02 +_FillRectPattern equ #4d38 +_Find_Parse_Formula equ #49b1 +_FindAlphaDn equ #491e +_FindAlphaUp equ #491b +_FindSym equ #42dc +_FiveExec equ #45b5 +_FixTempCnt equ #4912 +_FormEReal equ #4885 +_FormReal equ #488B +_FourExec equ #45b2 +_FPAdd equ #4072 +_FPDiv equ #4099 +_FPMult equ #4084 +_FPRecip equ #4096 +_FPSquare equ #4081 +_FPSub equ #406f +_Frac equ #4093 + +_Get_Tok_Strng equ #44F8 +_GetBaseVer equ #4b8e +_GetCSC equ #400f +_GetKey equ #486d +_GetLToOP1 equ #4573 +_GetTokLen equ #44f5 +_GrBufClr equ #4AD4 +_GrBufCpy equ #4789 +_GrphCirc equ #46f9 + +_HLTimes9 equ #40e4 +_HorizCmd equ #47c5 +_HomeUp equ #44bf +_HTimesL equ #4270 + +_IBounds equ #4aa4 +_IBoundsFull equ #4d4d +_ILine equ #4702 +_IncLstSize equ #4900 +_InsertList equ #4903 +_InsertMem equ #42df +_Int equ #40a5 +_Intgr equ #405d +_InvCmd equ #47e3 +_InvertRect equ #4cff +_InvOP1S equ #408d +_InvOP1SC equ #408a +_InvOP2S equ #4090 +_InvSub equ #4063 +_IOffset equ #4aa7 +_IPoint equ #4705 +_IsA2ByteTok equ #4291 +_IsEditEmpty equ #483A + +_JError equ #4a4d +_JErrorNo equ #4c03 +_JForceCmdNoChar equ #401e + +_KeyToString equ #452e + +_LCD_BUSY equ #4051 +_LCD_DRIVERON equ #4873 +_LdHLind equ #4000 +_LineCmd equ #47cb +_LnX equ #40ab +_Load_SFont equ #46b7 +_LoadPattern equ #4c51 +_LogX equ #40ae + +_Max equ #4057 +_MemChk equ #42cd +_MemClear equ #4a47 +_MemSet equ #4a4a +_Min equ #4054 +_Minus1 equ #406c +_Mov10B equ #413e +_Mov18B equ #46fc +_Mov9B equ #4141 +_Mov7B equ #414a +_Mov8B equ #4147 +_Mov9ToOP1 equ #416b +_Mov9OP1OP2 equ #416e +_Mov9ToOP2 equ #4171 +_MovFrOP1 equ #4174 +_Mul_HL equ #4270 + +_NewLine equ #4495 + +_OP1ExOP2 equ #4225 +_OP1ExOP3 equ #421f +_OP1ExOP4 equ #4222 +_OP1ExOP5 equ #4219 +_OP1ExOP6 equ #421c +_OP1ExpToDec equ #424c +_OP1Set0 equ #41d1 +_OP1Set1 equ #4192 +_OP1Set2 equ #419e +_OP1Set3 equ #4198 +_OP1Set4 equ #4195 +_OP1ToOP2 equ #4111 +_OP1ToOP3 equ #4105 +_OP1ToOP4 equ #40f9 +_OP1ToOP5 equ #4135 +_OP1ToOP6 equ #4132 +_OP2Set0 equ #41ce +_OP2Set1 equ #41aa +_OP2Set2 equ #41a1 +_OP2Set3 equ #418f +_OP2Set4 equ #418c +_OP2Set5 equ #4186 +_OP2Set60 equ #497b +_OP2Set8 equ #4183 +_OP2SetA equ #4189 +_OP2ToOP1 equ #4138 +_OP2ToOP3 equ #415f +_OP2ToOP4 equ #40fc +_OP2ToOP5 equ #412c +_OP2ToOP6 equ #412f +_OP3Set0 equ #41cb +_OP3Set1 equ #4180 +_OP3Set2 equ #419b +_OP3ToOP1 equ #4120 +_OP3ToOP2 equ #4102 +_OP3ToOP4 equ #40f6 +_OP3ToOP5 equ #4129 +_OP4Set0 equ #41c8 +_OP4Set1 equ #417d +_OP4ToOP1 equ #411a +_OP4ToOP2 equ #40ff +_OP4ToOP3 equ #4162 +_OP4ToOP5 equ #4126 +_OP4ToOP6 equ #4168 +_OP5Set0 equ #41c5 +_OP5ToOP1 equ #411d +_OP5ToOP2 equ #4108 +_OP5ToOP3 equ #4165 +_OP5ToOP4 equ #410e +_OP5ToOP6 equ #410b +_OP6ToOP1 equ #4117 +_OP6ToOP2 equ #4114 +_OP6ToOP5 equ #4123 + +_ParseInp equ #4966 +_PDspGrph equ #47c2 +_PixelTest equ #47d4 +_Plus1 equ #4069 +_PointCmd equ #47d1 +_PointOn equ #4a56 +_PopOP1 equ #4345 +_PopOP3 equ #4342 +_PopOP5 equ #433f +_PopReal equ #435a +_PopRealO1 equ #4357 +_PopRealO2 equ #4354 +_PopRealO3 equ #4351 +_PopRealO4 equ #434e +_PopRealO5 equ #434b +_PopRealO6 equ #4348 +_PosNo0Int equ #4234 +_PToR equ #40de +_PushOP1 equ #438a +_PushOP3 equ #4387 +_PushOP5 equ #4384 +_PushReal equ #4381 +_PushRealO1 equ #437e +_PushRealO2 equ #437b +_PushRealO3 equ #4378 +_PushRealO4 equ #4375 +_PushRealO5 equ #4372 +_PushRealO6 equ #436f +_PutAway equ #4039 +_PutC equ #446b +_PutMap equ #4468 +_PutPS equ #4477 +_PutPSB equ #4474 +_PutS equ #4471 +_PutTokString equ #485e +_PutToL equ #4582 + +_RandInit equ #4c21 +_Random equ #4b9d +_Rcl_StatVar equ #42c7 +_RclAns equ #4996 +_RclGDB2 equ #46f3 +_RclSysTok equ #49a2 +_RclVarSym equ #499f +_RclX equ #499c +_RclY equ #4999 +_RedimMat equ #48fd +_Regraph equ #47aa +_ReleaseBuffer equ #46A5 +_ReloadAppEntryVecs equ #4a50 +_RestoreDisp equ #478c +_RndGuard equ #409f +_RnFx equ #40a2 +_Round equ #40a8 +_RToD equ #4078 +_RToP equ #40e1 +_RunIndicOff equ #44d7 +_RunIndicOn equ #44d4 + +_SaveDisp equ #4ba3 +_SendVarCmd equ #48F1 +_SetFuncM equ #4762 +_SetXXOP1 equ #46c0 +_SetXXOP2 equ #46c3 +_SetXXXXOP2 equ #46c6 +_SFont_Len equ #46ba +_ShRAcc equ #41E6 +_Sin equ #40bd +_SinCosRad equ #40ba +_SqRoot equ #409c +_SrchVLstDn equ #4c36 +_SrchVLstUp equ #4c33 +_SStringLength equ #4c54 +_StMatEl equ #49a5 +_StoAns equ #498a +_StoGDB2 equ #46f0 +_StoOther equ #4993 +_StoRand equ #4e5e +_StoSysTok equ #4987 +_StoX equ #4990 +_StoY equ #498d +_StrCopy equ #444a +_StrLength equ #4a5c + +_Tan equ #40c3 +_TenX equ #40b7 +_ThreeExec equ #45ac +_Times2 equ #4066 +_TimesPt5 equ #407e +_ToFrac equ #4594 +_Trunc equ #4060 + +_UCLines equ #46c9 +_UnLineCmd equ #47ce +_UnOpExec equ #45a9 + +_VertCmd equ #47c8 +_VPutMap equ #44c5 +_VPutS equ #44c8 +_VPutSN equ #44cb +_VtoWHLDE equ #471d + +_XftoI equ #4726 +_XitoF equ #4720 +_XName equ #4279 +_XRootY equ #46d2 + +_YftoI equ #4723 +_YName equ #427c +_YtoX equ #46d5 + +_Zero16D equ #41b9 +_ZeroOP equ #41e0 +_ZeroOP1 equ #41d7 +_ZeroOP2 equ #41da +_ZeroOP3 equ #41dd +_ZmDecml equ #476e +_ZmFit equ #477a +_ZmInt equ #476b +_ZmPrev equ #4771 +_ZmSquare equ #477d +_ZmStats equ #46d8 +_ZmTrig equ #4780 +_ZmUsr equ #4774 +_ZooDefault equ #4786 + +;====================================================================== + +; system-defined ram variable address equates + +;====================================================================== + +; + + +appData equ #8000 +ramStart equ #8000 +ramCode equ #8100 +ramCodeEnd equ #822f +baseAppBrTab equ #8230 +bootTemp equ #8241 +appSearchPage equ #8293 +tempSwapArea equ #8295 +appID equ #837d +kbdScanCode equ #83d8 +kbdKey equ #83dd +kbdGetKy equ #83de +keyExtend equ #83df +contrast equ #83e0 +curTime equ #83e1 +curRow equ #83e2 +curCol equ #83e3 +curOffset equ #83e4 +curUnder equ #83e5 +ioFlag equ #83e6 +sndRecState equ #83e8 +ioErrState equ #83e9 +header equ #83ea +ioData equ #83f3 +bakHeader equ #83ff +OP1 equ #842b +OP1M equ #842d +OP2 equ #8436 +OP2EXT equ #843f +OP3 equ #8441 +OP3M equ #8443 +OP4 equ #844c +OP4M equ #844e +OP5 equ #8457 +OP5M equ #8459 +OP6 equ #8462 +OP6M equ #8464 +OP6EXT equ #846b +progToEdit equ #8472 +nameBuff equ #847a +equ_edit_save equ #8485 +OP2M equ #8485 +iMathPtr1 equ #8486 +iMathPtr2 equ #8488 +iMathPtr3 equ #848a +iMathPtr4 equ #848c +iMathPtr5 equ #848e +chkDelPtr1 equ #8490 +chkDelPtr2 equ #8492 +insDelPtr equ #8494 +upDownPtr equ #8496 +curY equ #8498 +curType equ #8499 +curXRow equ #849a +prevDData equ #849b +lFont_record equ #84a3 +sFont_record equ #84ab +menuActive equ #84b3 +menuAppDepth equ #84b4 +MenuCurrent equ #84b5 +ProgCurrent equ #84c1 +rclQueue equ #84d2 +rclQueueEnd equ #84d4 +indicMem equ #84d6 +indicCounter equ #84de +indicBusy equ #84df +apdSubTimer equ #84e0 +apdTimer equ #84e1 +cxMain equ #84e2 +cxPPutAway equ #84e4 +cxPutAway equ #84e6 +cxRedisp equ #84e8 +cxErrorEP equ #84ea +cxSizeWind equ #84ec +cxPage equ #84ee +cxCurApp equ #84ef +cxPrev equ #84f0 +monQH equ #850e +monQT equ #850f +monQueue equ #8510 +onSP equ #8520 +ramReturnData equ #8529 +errNo equ #854a +errSP equ #854b +errOffset equ #854d +bstCounter equ #8559 +flags equ #855b +tokVarPtr equ #85a1 +tokLen equ #85a3 +fOutDat equ #85a5 +asm_data_ptr1 equ #85af +asm_data_ptr2 equ #85b1 +asm_sym_ptr1 equ #85b3 +asm_sym_ptr2 equ #85b5 +asm_ind_call equ #85b7 +appRawKeyHandle equ #85b8 +appBank_jump equ #85c9 +appPage equ #85cb +customHeight equ #8612 +appBackUpScreen equ #8613 +textShadow equ #8913 +textShadCur equ #8993 +textShadTop equ #8995 +textShadAlph equ #8996 +textShadIns equ #8997 +appInfo equ #8998 +promptRow equ #89a2 +promptCol equ #89a3 +promptIns equ #89a4 +promptShift equ #89a5 +promptRet equ #89a6 +promptValid equ #89a8 +promptTop equ #89aa +promptCursor equ #89ac +promptTail equ #89ae +promptBtm equ #89b0 +varType equ #89b2 +varCurrent equ #89b3 +varClass equ #89bb +penCol equ #89df +penRow equ #89e0 +userMenuSA equ #89e1 +ioPrompt equ #8a41 +dImageWidth equ #8a42 +RectFillPHeight equ #8A42 +RectFillPWidth equ #8a43 +RectFillPattern equ #8a44 +saveSScreen equ #8a52 +statVars equ #8d58 +curGStyle equ #8e94 +curGY equ #8e95 +curGX equ #8e96 +curGY2 equ #8e97 +curGX2 equ #8e98 +freeSaveY equ #8e99 +freeSaveX equ #8e9a +XOffset equ #8ec8 +YOffset equ #8ec9 +lcdTallP equ #8eca +pixWideP equ #8ecb +pixWide_m_1 equ #8ecc +pixWide_m_2 equ #8ecd +lastEntryPTR equ #8ece +lastEntryStk equ #8ed0 +numLastEntries equ #90d0 +currLastEntry equ #90d1 +curInc equ #92de +uXmin equ #92f5 +uXmax equ #92fe +uXscl equ #9307 +uYmin equ #9310 +uYmax equ #9319 +uYscl equ #9322 +uThetMin equ #932b +uThetMax equ #9334 +uThetStep equ #933d +uTmin equ #9346 +uTmax equ #934f +uTStep equ #9358 +uPlotStart equ #9361 +unMax equ #936a +uu0 equ #9373 +uv0 equ #937c +unMin equ #9385 +uu02 equ #938e +uv02 equ #9397 +uw0 equ #93a0 +uPlotStep equ #93a9 +uXres equ #93b2 +uw02 equ #93bb +Xmin equ #93c7 +Xmax equ #93d0 +Xscl equ #93d9 +Ymin equ #93e2 +Ymax equ #93eb +Yscl equ #93f4 +ThetaMin equ #93fd +ThetaMax equ #9406 +ThetaStep equ #940f +TminPar equ #9418 +TmaxPar equ #9421 +Tstep equ #942a +PlotStart equ #9433 +nMax equ #943c +u0 equ #9445 +v0 equ #944e +nMin equ #9457 +u02 equ #9460 +v02 equ #9469 +w0 equ #9472 +PlotStep equ #947b +XresO equ #9484 +w02 equ #948d +smallEditRAM equ #949f +XFact equ #950b +YFact equ #9514 +Xres_int equ #951d +deltaX equ #951e +deltaY equ #9527 +shortX equ #9530 +shortY equ #9539 +lower equ #9542 +upper equ #954b +XOutSym equ #9558 +XOutDat equ #955a +YOutSym equ #955c +YOutDat equ #955e +inputSym equ #9560 +inputDat equ #9562 +prevData equ #9564 +TblMin equ #9676 +TblStep equ #967f +P1Type equ #968c +SavX1List equ #968d +SavY1List equ #9692 +SavF1List equ #9697 +P1FrqOnOff equ #96ab +P2Type equ #96ae +SavX2List equ #96af +SavY2List equ #96b4 +SavF2List equ #96b9 +P2FrqOnOff equ #96cd +P3Type equ #96d0 +SavX3List equ #96d1 +SavY3List equ #96d6 +SavF3List equ #96d8 +P3FrqOnOff equ #96ef +plotSScreen equ #9737 +seed1 equ #9a37 +seed2 equ #9a40 +cmdCursor equ #9a7e +editTop equ #9a82 +editCursor equ #9a84 +editTail equ #9a86 +editBtm equ #9a88 +editSym equ #9a94 +editDat equ #9a96 +winTop equ #9b33 +winBtm equ #9b34 +winLeftEdge equ #9b35 +winLeft equ #9b36 +winAbove equ #9b38 +winRow equ #9b3a +winCol equ #9b3c +fmtDigits equ #9b3e +fmtString equ #9b3f +fmtConv equ #9b80 +fmtLeft equ #9b92 +fmtIndex equ #9b94 +fmtMatSym equ #9b96 +fmtMatMem equ #9b98 +EQS equ #9b9a +tSymPtr1 equ #9ba6 +tSymPtr2 equ #9ba8 +chkDelPtr3 equ #9baa +chkDelPtr4 equ #9bac +tempMem equ #9bae +fpBase equ #9bb0 +FPS equ #9bb2 +OPBase equ #9bb4 +OPS equ #9bb6 +pTempCnt equ #9bb8 +cleanTmp equ #9bba +pTemp equ #9bbc +progPtr equ #9bbe +newDataPtr equ #9bc0 +appErr1 equ #9bc2 +appErr2 equ #9bcf + +symTable equ #fe66 + +;SYMBOLIC_DEBUG_END +;==================================== +; equates for fraction entry routines +;==================================== +fieldMax equ OP5 +fieldLen equ fieldMax+1 +fieldCol equ fieldLen+1 ; pencol of start +fieldRow equ fieldCol+1 ; penrow of start 3 rows above char +fieldInput equ fieldRow+1 ; 9 bytes, +wholeMax equ tempSwapArea +wholeLen equ wholeMax+1 +wholeCol equ wholeLen+1 ; pencol of start +wholeRow equ wholeCol+1 ; penrow of start 3 rows above char +wholeInput equ wholeRow+1 ; 9 bytes, +; +numerMax equ wholeInput+9 +numerLen equ numerMax+1 +numerCol equ numerLen+1 ; pencol of start +numerRow equ numerCol+1 ; penrow of start +numerInput equ numerRow+1 ; 9 bytes, +; +denomMax equ numerInput+9 +denomLen equ denomMax+1 +denomCol equ denomLen+1 ; pencol of start +denomRow equ denomCol+1 ; penrow of start +denomInput equ denomRow+1 ; 9 bytes, +; +fracLineLen equ denomInput+9 +fracLineCol equ fracLineLen+1 +; +fracRightEdge equ fracLineCol+1 +; +curPosition equ fracRightEdge+1 +; +numerSpaces equ curPosition+1 +denomSpaces equ numerSpaces+1 +haveFrac equ 3 +haveUnit equ 4 +incCurPos equ 5 + + +; +;====================================================================== +; system variable equates +;====================================================================== +; entry points : rclsystok, stosystok +; +; vars with no restriction +; +XSCLt equ 3 ; 'xscl' 4 +YSCLt equ 4 ; 'yscl' 4 +; +; vars rounded to 10 digits +; +XMINt EQU #0A ; 'xMin' 4 +XMAXt EQU #0B ; 'xMax' 4 +YMINt EQU #0C ; 'yMin' 4 +YMAXt EQU #0D ; 'yMax' 4 +TBLMINt EQU #1A ; 'TBLMIN' +; +; rouned to 10 digits, and positve integers +; +PLOTSTARTt equ #1b ; 'nstart' 5 +UPLOTSTARTt equ #1c ; 'znstart' 6 + +; vars cannot be 0 +; +TBLSTEPt EQU #21 ; 'TBLSTEP' +TSTEPt EQU #22 ; 'tStep' 5 +THETSTEPt EQU #23 ; Ltheta,'Step' 5 +UTSTEPt EQU #24 ; 'ztStep' 6 +UTHSTEPt EQU #25 ; 'z',Ltheta,'Step' 6 +; +; special limits on these +; +DELTAXt EQU #26 ; LcapDelta,'x' 2 +DELTAYt EQU #27 ; LcapDelta,'y' 2 +; +; special limits on these +; +XFACTt EQU #28 ; 'xFact' 5 +YFACTt EQU #29 ; 'yFact' 5 +; +; sys var list +; +TBLINPUTt equ #2a +; +; +; +PLOTSTEPt equ #34 +UPLOTSTEPt equ #35 +; +XRESt equ #36 +UXRESt equ #37 +; +; special token used by input/prompt for storing value to variable + +INPUTt equ #40 ; set up for store for input/prompt + +; special token used by graph math intersection routine to indicate +; list data + +ISECTt equ #41 ; list data follows this +; +;========== automatic power down time out value (<= 7 minutes) +apdTimeOut equ 5 ;automatic power down time (minutes) + +;========== interrupt equate +iAll equ 1011b + +;========== i/o ports +intrptEnPort equ 3 ; interrupt enable (in/out) +memPageAPort equ 6 ; memory page a (i/o) +LCDInstPort equ #10 +LCDDataPort equ #11 + + +;========== common subroutine rst numbers +rOP1TOOP2 EQU #08 +rFINDSYM EQU #10 +rPUSHREALO1 EQU #18 +rMOV9TOOP1 EQU #20 +rFPADD EQU #30 + +;============error handler equates/macros +APP_PUSH_ERRORH EQU #59 +APP_POP_ERRORH EQU #5C + +;========== run indicators + +busyPause equ %10101010 +busynNormal equ %11110000 + +;====================================================================== +; system and state flags +;====================================================================== +; + +trigFlags equ 0 ;trigonometry mode settings +trigDeg equ 2 ; 1=degrees, 0=radians + +kbdFlags equ 0 ;keyboard scan +kbdScr equ 3 ; 1=scan code ready +kbdKeyPress equ 4 ; 1=key has been pressed + +doneFlags equ 0 ;display "done" +donePrgm equ 5 ; 1=display "done" after prgm + +ioDelFlag equ 0 +inDelete equ 0 ;1 = delete screen + +;---------------------------------------------------------------------- +editFlags equ 1 +editOpen equ 2 ; 1=edit buffer is open + +monFlags equ 1 ;monitor flags +monAbandon equ 4 ; 1=don't start any long process + ; in put away (#715) +;---------------------------------------------------------------------- +plotFlags equ 2 ;plot generation flags +plotTrace equ 0 +plotLoc equ 1 ; 0=bkup & display, 1=display only +plotDisp equ 2 ; 1=plot is in display, 0=text in display + + +grfModeFlags equ 2 ;graph mode settings +grfFuncM equ 4 ; 1=function graph +grfPolarM equ 5 ; 1=polar graph +grfParamM equ 6 ; 1=parametric graph +grfRecurM equ 7 ; 1=recursion graph + +graphFlags equ 3 +graphProg equ 1 ; 1=graph in progress +graphDraw equ 0 ; 0=graph is valid, 1=redraw graph + +grfDBFlags equ 4 +grfDot equ 0 ; 0=line, 1=dot +grfSimul equ 1 ; 0=sequential, 1=simultaneous +grfGrid equ 2 ; 0=no grid, 1=grid +grfPolar equ 3 ; 0=rectangular, 1=polar coordinates +grfNoCoord equ 4 ; 0=display coordinates, 1=off +grfNoAxis equ 5 ; 0=axis, 1=no axis +grfLabel equ 6 ; 0=off, 1=axis label + +textFlags equ 5 ;text output flags +textEraseBelow equ 1 ; 1=erase line below small char +textScrolled equ 2 ; 1=screen scrolled +textInverse equ 3 ; 1=display inverse bit-map +textInsMode equ 4 ; 0=overstrike, 1=insert mode + +parsFlag2 equ 7 ;parser flags +numOP1 equ 0 ; 1=result in op1, 0=no result + +newDispF equ 8 ;derivative mode flags +preClrForMode equ 0 ; 1=help blink on mode screen + +apdFlags equ 8 ;automatic power-down +apdAble equ 2 ; 1=apd enabled +apdRunning equ 3 ; 1=apd clock running + + +web_err_mask equ #60 + +onFlags equ 9 ;on key flags +onRunning equ 3 +onInterrupt equ 4 ; 1=on key interrupt request + +statFlags equ 9 ;statistics flags +statsValid equ 6 ; 1=stats are valid + +fmtFlags equ 10 ;numeric format flags +fmtExponent equ 0 ; 1=show exponent, 0=no exponent +fmtEng equ 1 ; 1=engineering notion, 0=scientific +fmtHex equ 2 ; 1=hexadecimal +fmtOct equ 3 ; 1=octal +fmtBin equ 4 ; 1=binary +; +numMode equ 10 +fmtReal equ 5 +fmtRect equ 6 +fmtPolar equ 7 + +realMode equ 5 +rectMode equ 6 +polarMmode equ 7 +; ; if hex and oct both = 1 +; ; then bin=0 means >frac +; ; bin=1 means >dms +fmtBaseMask equ %00011100 ; mask to base flags +fmtBaseShift equ 2 ; offset to base flags +; +; check if these are used by numform, +; +; equ 6 +; equ 7 + +fmtOverride equ 11 ;copy of fmtflags with conversion override + +fmtEditFlags equ 12 ;numeric editing flags +fmtEdit equ 0 ; 1=format number for editing + +curFlags equ 12 ;cursor +curAble equ 2 ; 1=cursor flash is enabled +curOn equ 3 ; 1=cursor is showing +curLock equ 4 ; 1=cursor is locked off + +appFlags equ 13 ;application flags +appWantIntrpt equ 0 ; 1=want on key interrupts +appTextSave equ 1 ; 1=save characters in textshadow +appAutoScroll equ 2 ; 1=auto-scroll text on last line +appMenus equ 3 ; 1=process keys that bring up menus + ; 0=check lock menu flag +appLockMenus equ 4 ; 1=ignore menu keys + ; 0=switch to home screen and bring up menu +appCurGraphic equ 5 ; 1=graphic cursor +appCurWord equ 6 ; 1=text cursor covers entire word +appExit equ 7 ; 1=application handles [exit] key itself + +appWantIntrptF equ 1<Frac +SimpKeyF equ 1 ;Used for Simp K. +RatD1K equ 1 ;also used to show denominator=1000 +FinalType equ 2 ;1=final type is improper 0=type is simple +FinalFrac equ 3 ;set if final fraction result expected. +ManDtoF equ 4 ;manual simp=1, Dec->frac bit. +ManForceS equ 5 ;manual simp=1, Abc=0; force simplify anyhow. +ManAdjW equ 6 ;manual simp=1, Abc=0; Adjust whole flag. +ManBin equ 7 ;manual simp=1, Binop set. + + +;flags for fraction math routines: +FracFlags3 equ 39 +FNormOver equ 0 ;Fraction Normalization Override if set. +DivSmallNum equ 1 ;set if Frac Numerator < denominator. +IntDivDisp equ 2 ;integer divide display flag. +StrictInt equ 3 ;strict integer check by intdiv if set. +yxRatF equ 4 ;y^x rational approximation flag. +nid equ 5 ;1 if non integer decimal +SimpDisp equ 6 ;1 if need to display frac simplify factor. +HadTrueMixed equ 7 ;at least one true fraction in an expression. +;(HadTrueMixed is needed by >Ab/c<>d/e so that if any mixed fraction, then +; if convert, will stay b/c if b/c mode & not convert back to mixed.) + +; +getSendFlg equ 47 +comFailed equ 3 ; 1 = get/send communication failed +; +; +apiFlg3 equ 52 +; +apiFlg4 equ 53 +fullScrnDraw equ 2 ; draw into last row/col of screen + +xapFlag0 equ 43 ; external app flags +xapFlag1 equ 44 +xapFlag2 equ 45 +xapFlag3 equ 46 + +plotFlag3 equ 47 +bufferOnly equ 6 +useFastCirc equ 4 + +; +varTypeMask equ #1f +varGraphRef equ 6 + +;====================================================================== +; character font equates +;====================================================================== +; +LrecurN equ #001 +LrecurU equ #002 +LrecurV equ #003 +LrecurW equ #004 +Lconvert equ #005 +LsqUp equ #006 +LsqDown equ #007 +Lintegral equ #008 +Lcross equ #009 +LboxIcon equ #00a +LcrossIcon equ #00b +LdotIcon equ #00c +LsubT equ #00d ;small capital t for parametric mode. +LcubeR equ #00e ;slightly different 3 for cubed root. +LhexF equ #00f +Lroot equ #010 +Linverse equ #011 +Lsquare equ #012 +Langle equ #013 +Ldegree equ #014 +Lradian equ #015 +Ltranspose equ #016 +LLE equ #017 +LNE equ #018 +LGE equ #019 +Lneg equ #01a +Lexponent equ #01b +Lstore equ #01c +Lten equ #01d +LupArrow equ #01e +LdownArrow equ #01f +Lspace equ #020 +Lexclam equ #021 +Lquote equ #022 +Lpound equ #023 +Lfourth equ #024 +Lpercent equ #025 +Lampersand equ #026 +Lapostrophe equ #027 +LlParen equ #028 +LrParen equ #029 +Lasterisk equ #02a +LplusSign equ #02b +Lcomma equ #02c +Ldash equ #02d +Lperiod equ #02e +Lslash equ #02f +L0 equ #030 +L1 equ #031 +L2 equ #032 +L3 equ #033 +L4 equ #034 +L5 equ #035 +L6 equ #036 +L7 equ #037 +L8 equ #038 +L9 equ #039 +Lcolon equ #03a +Lsemicolon equ #03b +LLT equ #03c +LEQ equ #03d +LGT equ #03e +Lquestion equ #03f +LatSign equ #040 +LcapA equ #041 +LcapB equ #042 +LcapC equ #043 +LcapD equ #044 +LcapE equ #045 +LcapF equ #046 +LcapG equ #047 +LcapH equ #048 +LcapI equ #049 +LcapJ equ #04a +LcapK equ #04b +LcapL equ #04c +LcapM equ #04d +LcapN equ #04e +LcapO equ #04f +LcapP equ #050 +LcapQ equ #051 +LcapR equ #052 +LcapS equ #053 +LcapT equ #054 +LcapU equ #055 +LcapV equ #056 +LcapW equ #057 +LcapX equ #058 +LcapY equ #059 +LcapZ equ #05a +Ltheta equ #05b +Lbackslash equ #05c +LrBrack equ #05d +Lcaret equ #05e +Lunderscore equ #05f +Lbackquote equ #060 +La equ #061 +Lb equ #062 +Lc equ #063 +;Ld equ #064 +;Le equ #065 +Lf equ #066 +Lg equ #067 +Lh equ #068 +Li equ #069 +Lj equ #06a +Lk equ #06b +Ll equ #06c +Lm equ #06d +Ln equ #06e +Lo equ #06f +Lp equ #070 +Lq equ #071 +Lr equ #072 +Ls equ #073 +;Lt equ #074 +Lu equ #075 +Lv equ #076 +Lw equ #077 +Lx equ #078 +Ly equ #079 +Lz equ #07a +LlBrace equ #07b +Lbar equ #07c +LrBrace equ #07d +Ltilde equ #07e +LinvEQ equ #07f +Lsub0 equ #080 +Lsub1 equ #081 +Lsub2 equ #082 +Lsub3 equ #083 +Lsub4 equ #084 +Lsub5 equ #085 +Lsub6 equ #086 +Lsub7 equ #087 +Lsub8 equ #088 +Lsub9 equ #089 +LcapAAcute equ #08a +LcapAGrave equ #08b +LcapACaret equ #08c +LcapADier equ #08d +LaAcute equ #08e +LaGrave equ #08f +LaCaret equ #090 +LaDier equ #091 +LcapEAcute equ #092 +LcapEGrave equ #093 +LcapECaret equ #094 +LcapEDier equ #095 +LeAcute equ #096 +LeGrave equ #097 +LeCaret equ #098 +LeDier equ #099 +LcapIAcute equ #09a +LcapIGrave equ #09b +LcapICaret equ #09c +LcapIDier equ #09d +LiAcute equ #09e +LiGrave equ #09f +LiCaret equ #0a0 +LiDier equ #0a1 +LcapOAcute equ #0a2 +LcapOGrave equ #0a3 +LcapOCaret equ #0a4 +LcapODier equ #0a5 +LoAcute equ #0a6 +LoGrave equ #0a7 +LoCaret equ #0a8 +LoDier equ #0a9 +LcapUAcute equ #0aa +LcapUGrave equ #0ab +LcapUCaret equ #0ac +LcapUDier equ #0ad +LuAcute equ #0ae +LuGrave equ #0af +LuCaret equ #0b0 +LuDier equ #0b1 +LcapCCed equ #0b2 +LcCed equ #0b3 +LcapNTilde equ #0b4 +LnTilde equ #0b5 +Laccent equ #0b6 +Lgrave equ #0b7 +Ldieresis equ #0b8 +LquesDown equ #0b9 +LexclamDown equ #0ba +Lalpha equ #0bb +Lbeta equ #0bc +Lgamma equ #0bd +LcapDelta equ #0be +Ldelta equ #0bf +Lepsilon equ #0c0 +LlBrack equ #0c1 +Llambda equ #0c2 +Lmu equ #0c3 +Lpi equ #0c4 +Lrho equ #0c5 +LcapSigma equ #0c6 +Lsigma equ #0c7 +Ltau equ #0c8 +Lphi equ #0c9 +LcapOmega equ #0ca +LxMean equ #0cb +LyMean equ #0cc +LsupX equ #0cd +Lellipsis equ #0ce +Lleft equ #0cf +Lblock equ #0d0 +Lper equ #0d1 +Lhyphen equ #0d2 +Larea equ #0d3 +Ltemp equ #0d4 +Lcube equ #0d5 +Lenter equ #0d6 +LimagI equ #0d7 +Lphat equ #0d8 +Lchi equ #0d9 +LstatF equ #0da +Llne equ #0db +LlistL equ #0dc +LfinanN equ #0dd +L2_r_paren equ #0de +LblockArrow equ #0df +LcurO equ #0e0 +LcurO2 equ #0e1 +LcurOcapA equ #0e2 +LcurOa equ #0e3 +LcurI equ #0e4 +LcurI2 equ #0e5 +LcurIcapA equ #0e6 +LcurIa equ #0e7 +LGline equ #0e8 ; = 0 +LGthick equ #0e9 ; = 1 +LGabove equ #0ea ; = 2 +LGbelow equ #0eb ; = 3 +LGpath equ #0ec ; = 4 +LGanimate equ #0ed ; = 5 +LGdot equ #0ee ; = 6 +LGpBlk equ #0ef ;up arrow and block in solver +LDnBlk equ #0f0 ;down arrow and block in solver +LcurFull equ #0f1 ;note: must be last char (putmap checks) + +;========= floating point + +FPLEN equ 9 ;length of a floating-point number + +;========= constant table equates + +drConst equ 0 +pi2Const equ 1 +pi4Const equ 2 +logeConst equ 3 +piConst equ 4 +DtoRConst equ 5 +ln10 equ 6 + +;========== text screen +textRows equ 8 +textCols equ 16 + +;========== alphatext screen +alphabuffersize equ 16 +; +;========== msc fraction equates +mantSignBit equ 7 ;msbit of data type byte is set if negative. +redF equ 1 ;reduced if 0, unreduced if 1. +unredF equ 1 ;reduced if 0, unreduced if 1. +simpF equ 0 ;simple if 0, mixed if 1. +mixedF equ 0 ;simple if 0, mixed if 1. +; + +; +; + +;====== keyboard key names +; +; key presses that do not echo into the display +; and are not application or menu loading key presses +; +kRight EQU #001 +kLeft EQU #002 +kUp EQU #003 +kDown EQU #004 +kEnter EQU #005 +kAlphaEnter EQU #006 +kAlphaUp EQU #007 +kAlphaDown EQU #008 +kClear EQU #009 +kDel EQU #00A +kIns EQU #00B +kRecall EQU #00C +kLastEnt EQU #00D +kBOL EQU #00E +kEOL EQU #00F +; +kSelAll EQU #010 +kUnselAll EQU #011 +kLtoTI82 EQU #012 +kBackup EQU #013 +kRecieve EQU #014 +kLnkQuit EQU #015 +kTrans EQU #016 +kRename EQU #017 +kOverw EQU #018 +kOmit EQU #019 +kCont equ #01A +kLtoTI83 equ #01B +kSendApp equ #01C +kvApps equ #01C +kSendId equ #01D +kSendSW equ #01E +kvALL equ #01F +kvSendType equ #020 ;send a particular data type (in kextend) +kNoWay EQU #021 +kYes EQU #022 +kAbout equ #023 ;about screen +kApp equ #024 +; +kProgExec equ #025 +kListflag equ #026 +; +;open for expansion 028h..02bh +; + +menustart equ #02c +; +; key presses that do not echo into the display +; and are menu switching key presses +; +kAreYouSure equ #02C +kPrgm equ #02D +kZoom equ #02E ; PULL DOWN +kDraw equ #02F +kSPlot equ #030 +kStat equ #031 +kMath equ #032 +kTest equ #033 +kAppsMenu equ #034 +kVars equ #035 +kMem equ #036 +kConstSetmenu equ #037 +kConvMenu equ #038 +kTrigmenu equ #039 +kLIST equ #03A +kConstMenu equ #03B +; +menuend equ kConstMenu +; +kConst EQU #03C +; +; +kAlpha equ #03d +kCatalog equ #03e ; catalog +kInputDone equ #3f + +; +; key presses that do not echo into the display +; and are context switching key presses +; +kQuit equ #040 +kLinkIO equ #041 +kChkApps equ #042 ; Check Apps +kStatEd equ #043 +kGraph equ #044 +kMode equ #045 +kPrgmEd equ #046 ; PROGRAM EDIT +kPrgmCr equ #047 ; PROGRAM CREATE +kWindow equ #048 ; RANGE EDITOR +kYequ equ #049 ; EQUATION EDITOR +kTable equ #04A ; TABLE EDITOR +kTblSet equ #04B ; TABLE SET +kChkRAM equ #04C ; CHECK RAM +kDelMem equ #04D ; DELETE MEM +kResetMem equ #04E ; RESET MEM +kResetDef equ #04F ; RESET DEFAULT +kPrgmInput EQU #050 ; PROGRAM INPUT +kZFactEd EQU #051 ; ZOOM FACTOR EDITOR +kError EQU #052 ; ERROR +kExtApps EQU #053 ; Extra Applications. NEW +kSolveRoot equ #054 ; SOLVE EDITOR +kStatP equ #055 ; stat plot +kConstEd equ #056 ; Constant equ Editor. +kPrgmSetVar equ #057 ; SetMenu in a Program. +kFormat equ #058 ; FORMAT +; +; +append equ kFormat +; +; 58h - 59h are empty for growth +; +echoStart1 equ #05a +; +; conditional keys that if in prog edit will echo +; or if not in prog edit go to the graph screen +; 'trace' , 'zooms' +; +; +kTrace equ #05a +kZFit equ #05b +kZIn equ #05c +kZOut equ #05d +kZPrev equ #05e +kZBox equ #05f +kZDecml equ #060 +kSetZm equ #061 +kZSquar equ #062 +kZStd equ #063 +kZTrig equ #064 +kZQuad1 equ #065 +;kusrzm equ 065h +;kzsto equ 066h +kZInt equ #067 +kZStat equ #068 +; +; conditional keys that if in prog edit or if the +; graph screen is not displayed will echo, else will +; go to the graph screen. 'draw' menu, eval +echoStart2 equ #069 +; +; +kSelect equ #069 +kCircl equ #06a +kClDrw equ #06b +kLine equ #06c +kPen equ #06d +kPtChg equ #06e +kPtOff equ #06f +kPtOn equ #070 +kVert equ #071 +kHoriz equ #072 +kText equ #073 +kTanLn equ #074 +kManFit equ #075 +; +; these keys will always force to graph mode +; +kEval equ #076 +; +echoStart equ #07d +; +; key presses that echo into a buffer +; +kRemain equ #07d ;only needed to display 'r' +kPlot3 equ #07e +kListName equ #07f +kAdd equ #080 +kSub equ #081 +kMul equ #082 +kDiv equ #083 +kExpon equ #084 +kLParen equ #085 +kRParen equ #086 +kLBrack equ #087 +kRBrack equ #088 +kShade equ #089 +kStore equ #08a +kComma equ #08b +kChs equ #08c +kDecPnt equ #08d +k0 equ #08e +k1 equ #08f +k2 equ #090 +k3 equ #091 +k4 equ #092 +k5 equ #093 +k6 equ #094 +k7 equ #095 +k8 equ #096 +k9 equ #097 +kEE equ #098 +kSpace equ #099 +kCapA EQU #09A +kCapB EQU #09B +kCapC EQU #09C +kCapD EQU #09D +kCapE EQU #09E +kCapF EQU #09F +kCapG EQU #0A0 +kCapH EQU #0A1 +kCapI EQU #0A2 +kCapJ EQU #0A3 +kCapK EQU #0A4 +kCapL EQU #0A5 +kCapM EQU #0A6 +kCapN EQU #0A7 +kCapO EQU #0A8 +kCapP EQU #0A9 +kCapQ EQU #0AA +kCapR EQU #0AB +kCapS EQU #0AC +kCapT EQU #0AD +kCapU EQU #0AE +kCapV EQU #0AF +kCapW EQU #0B0 +kCapX EQU #0B1 +kCapY EQU #0B2 +kCapZ EQU #0B3 +kVarx EQU #0B4 +kPi EQU #0B5 +kInv EQU #0B6 +kSin EQU #0B7 +kASin EQU #0B8 +kCos EQU #0B9 +kACos EQU #0BA +kTan EQU #0BB +kATan EQU #0BC +kSquare EQU #0BD +kSqrt EQU #0BE +kLn EQU #0BF +kExp EQU #0C0 +kLog EQU #0C1 +kALog EQU #0C2 +kToABC EQU #0C3 +; +;kclrtbl equ #0c4h +; +kAns equ #0c5 +kColon equ #0c6 +; + +kUnit equ #0c7 ; new +kFracSlash equ #0c8 ; new +kRoot equ #0c9 +; +kQuest equ #0ca ; question mark +kQuote equ #0cb ; " +kTheta equ #0cc +kIf equ #0cd +kThen equ #0ce +kElse equ #0cf +kFor equ #0d0 +kWhile equ #0d1 +kRepeat equ #0d2 +kEnd equ #0d3 +kPause equ #0d4 +kLbl equ #0d5 +kGoto equ #0d6 +kISG equ #0d7 +kDSL equ #0d8 +kMenu equ #0d9 +kExec equ #0da +kReturn equ #0db +kStop equ #0dc +kInput equ #0dd +kPrompt equ #0de +kDisp equ #0df +kDispG equ #0e0 +kDispT equ #0e1 +kOutput equ #0e2 +kGetKey equ #0e3 +kClrHome equ #0e4 +; +;kprtscr equ #0e5 +; +kPercent equ #0e6 ;% new +kMixSimp equ #0e7 ; new +kFracDec equ #0e8 ; new +kSimp equ #0e9 ; new +kUnredF equ #0ea ; new +kIDiv equ #0eb ; new +kConvert equ #0ec ; new +kLBrace equ #0ed +kRBrace equ #0ee +kL1A equ #0ef +kL2A equ #0f0 +kL3A equ #0f1 +kL4A equ #0f2 +kL5A equ #0f3 +kL6A equ #0f4 +kConvLength equ #0f5 ;1st byte of conversion key. +kConvArea equ #0f6 ;1st byte of conversion key. +kConvVolume equ #0f7 ;1st byte of conversion key. +kConvTime equ #0f8 ;1st byte of conversion key. +kConvTemp equ #0f9 ;1st byte of conversion key. +kConvMass equ #0fa ;1st byte of conversion key. +kConvSpeed equ #0fb ;1st byte of conversion key. +; +; this key means that it is a 2 byte keycode +; there are 2 of these keys be careful +; +; +kExtendEcho2 equ #0fc +; +; +; this key means that the key press is one that echos +; into a buffer, and it is a 2 byte key code, go look at +; (extecho) for the key value +; +kExtendEcho equ #0fe +; +kE1BT equ 0 + +kDrawInv equ kE1BT +kDrawF equ kE1BT+1 +kPixelOn equ kE1BT+2 +kPixelOff equ kE1BT+3 +kPxlTest equ kE1BT+4 +kRCGDB equ kE1BT+5 +kRCPic equ kE1BT+6 +kSTGDB equ kE1BT+7 +kSTPic equ kE1BT+8 +kAbs equ kE1BT+9 +kTEqu equ kE1BT+10 ; == +kTNoteQ equ kE1BT+11 ; <> +kTGT equ kE1BT+12 ; > +kTGTE equ kE1BT+13 ; > = +kTLT equ kE1BT+14 ; < +kTLTE equ kE1BT+15 ; < = + +kAnd equ kE1BT+16 +kOr equ kE1BT+17 +kXor equ kE1BT+18 +kNot equ kE1BT+19 + +;klr1 equ kE1BT+20 + +kXRoot equ kE1BT+21 +kCube equ kE1BT+22 +kCbRt equ kE1BT+23 ; cube root +kToDec equ kE1BT+24 +; +kCubicR equ kE1BT+25 +kQuartR equ kE1BT+26 +; +kPlot1 equ kE1BT+27 +kPlot2 equ kE1BT+28 +; + +kRound equ kE1BT+29 +kIPart equ kE1BT+30 +kFPart equ kE1BT+31 +kInt equ kE1BT+32 + +kRand equ kE1BT+33 +kNPR equ kE1BT+34 +kNCR equ kE1BT+35 +kXFactorial equ kE1BT+36 + +kRad equ kE1BT+37 +kDegr equ kE1BT+38 ; degrees conv +kApost equ kE1BT+39 +kToDMS equ kE1BT+40 +kRtoPo equ kE1BT+41 ; r +kRtoPr equ kE1BT+42 +kPtoRx equ kE1BT+43 +kPtoRy equ kE1BT+44 + +kRowSwap equ kE1BT+45 +kRowPlus equ kE1BT+46 +kTimRow equ kE1BT+47 +kTRowP equ kE1BT+48 + +kSortA equ kE1BT+49 +kSortD equ kE1BT+50 +kSeq equ kE1BT+51 + +kMin equ kE1BT+52 +kMax equ kE1BT+53 +kMean equ kE1BT+54 +kMedian equ kE1BT+55 +kSum equ kE1BT+56 +kProd equ kE1BT+57 + +kDet equ kE1BT+58 +kTransp equ kE1BT+59 +kDim equ kE1BT+60 ; same as one in list +kFill equ kE1BT+61 ; same as one in list +kIdent equ kE1BT+62 +kRandm equ kE1BT+63 +kAug equ kE1BT+64 + +kLstMode equ kE1BT+65 +;available equ kE1BT+66 + +kmRad equ kE1BT+67 +kmDeg equ kE1BT+68 +kmNormF equ kE1BT+69 +kmSci equ kE1BT+70 +kFix equ kE1BT+71 +kmFloat equ kE1BT+72 +kSetMenu equ kE1BT+73 +kEOFrac equ kE1BT+74 + +kBoyIcon equ kE1BT+75 +kTreeIcon equ kE1BT+76 +kFaceIcon equ kE1BT+77 +kCircleIcon equ kE1BT+78 +kDiamondIcon equ kE1BT+79 +kStarIcon equ kE1BT+80 +kDollarIcon equ kE1BT+81 +;available equ kE1BT+82 +;available equ kE1BT+83 + +kFNOn equ kE1BT+84 +kFNOff equ kE1BT+85 + +kPlotsOn equ kE1BT+86 +kPlotsPff equ kE1BT+87 + +kPixelChg equ kE1BT+88 + +kSendMBL equ kE1BT+89 +kRecvMBL equ kE1BT+90 + +kBoxPlot equ kE1BT+ 91 +kBoxIcon equ kE1BT+ 92 + +kCrossIcon equ kE1BT+ 93 +kDotIcon equ kE1BT+ 94 + +kE2BT equ kE1BT+95 + +kSeqential equ kE2BT ;105 +kSimulG equ kE2BT+1 ;106 +kCoordOn equ kE2BT+2 ;107 +kCoordOff equ kE2BT+3 ;108 +kDrawLine equ kE2BT+4 ;109 +kDrawDot equ kE2BT+5 ;110 +kAxisOn equ kE2BT+6 ;111 +kAxisOff equ kE2BT+7 ;112 +kGridOn equ kE2BT+8 ;113 +kGridOff equ kE2BT+9 ;114 +kLblOn equ kE2BT+10 ;115 +kOblOff equ kE2BT+11 ;116 +kPolarG equ kE2BT+12 ;117 +kRectG equ kE2BT+13 ;118 + +kL1 equ kE2BT+14 ;119 = 77h +kL2 equ kE2BT+15 +kL3 equ kE2BT+16 +kL4 equ kE2BT+17 +kL5 equ kE2BT+18 +kL6 equ kE2BT+19 + +kMatA equ kE2BT+20 +kMatB equ kE2BT+21 +kMatC equ kE2BT+22 +kMatD equ kE2BT+23 +kMatE equ kE2BT+24 + +kXmin EQU kE2BT+25 +kXmax EQU kE2BT+26 +kXscl EQU kE2BT+27 +kYmin EQU kE2BT+28 +kYmax EQU kE2BT+29 +kYscl EQU kE2BT+30 +kTmin EQU kE2BT+31 +kTmax EQU kE2BT+32 +kTStep EQU kE2BT+33 +kOmin EQU kE2BT+34 +kOmax EQU kE2BT+35 +kOStep EQU kE2BT+36 +ku0 EQU kE2BT+37 +kv0 EQU kE2BT+38 +knMin EQU kE2BT+39 +knMax EQU kE2BT+40 +kDeltaY EQU kE2BT+41 +kDeltaX EQU kE2BT+42 + +kZXmin EQU kE2BT+43 +kZXmax EQU kE2BT+44 +kZXscl EQU kE2BT+45 +kZYmin EQU kE2BT+46 +kZYmax EQU kE2BT+47 +kZYscl EQU kE2BT+48 +kZTmin EQU kE2BT+49 +kZTmax EQU kE2BT+50 +kZTStep EQU kE2BT+51 +kZOmin EQU kE2BT+52 +kZOmax EQU kE2BT+53 +kZOStep EQU kE2BT+54 +; +kABC equ kE2BT+55 +kBC equ kE2BT+56 +kAutoSimp equ kE2BT+57 +kManSimp equ kE2BT+58 + +kDelLast equ kE2BT+59 +ksingleC equ kE2BT+60 +kMultiC equ kE2BT+61 + +kPic1 equ kE2BT+62 +kPic2 equ kE2BT+63 +kPic3 equ kE2BT+64 + +kDelVar equ kE2BT+65 +kGetCalc equ kE2BT+66 + +kStndrd equ kE2BT+67 +kParam equ kE2BT+68 +kPolar equ kE2BT+69 +kAFillOn equ kE2BT+70 +kAFillOff equ kE2BT+71 +kACalcOn equ kE2BT+72 +kACalcOff equ kE2BT+73 + +kSetConst equ kE2BT+74 +; +kGraphStyle equ kE2BT+75 +; +kExprOn EQU kE2BT+76 +kExprOff EQU kE2BT+77 +kStatA EQU kE2BT+78 +kStatB EQU kE2BT+79 +kStatC EQU kE2BT+80 +kCorr EQU kE2BT+81 +kStatD EQU kE2BT+82 +kStatE EQU kE2BT+83 +kRegEq EQU kE2BT+84 +kMinX EQU kE2BT+85 +kQ1 EQU kE2BT+86 +kMD EQU kE2BT+87 +kQ3 EQU kE2BT+88 +kMaxX EQU kE2BT+89 +kStatX1 EQU kE2BT+90 +kStatY1 EQU kE2BT+91 +kStatX2 EQU kE2BT+92 +kStatY2 EQU kE2BT+93 +kStatX3 EQU kE2BT+94 +kStatY3 EQU kE2BT+95 +kTblMin EQU kE2BT+96 +kTblStep EQU kE2BT+97 +kSetupLst EQU kE2BT+98 +kClrAllLst EQU kE2BT+99 +kLogistic EQU kE2BT+100 +kc1 equ kE2BT+101 ;constant c1 +kc2 equ kE2BT+102 ;constant c2 +kc3 equ kE2BT+103 ;constant c3 +kc4 equ kE2BT+104 ;constant c4 +kPlotStart equ kE2BT+105 ; plotstart +kZPlotStart equ kE2BT+106 ; zplotstart +kXFact equ kE2BT+107 ; xfact +kYFact equ kE2BT+108 ; yfact +kMaxY equ kE2BT+109 ; maxy +kTblInput equ kE2BT+110 ; web off +kPlotStep equ kE2BT+111 +kZPlotStep equ kE2BT+112 +kSelectA equ kE2BT+113 +kZFitA equ kE2BT+114 +kOneVar equ kE2BT+115 +kTwoVar equ kE2BT+116 +kLR equ kE2BT+117 +kLRExp equ kE2BT+118 +kLRLn equ kE2BT+119 +;klrpwr equ kE2BT+ +;kmanfit equ kE2BT+ +kMedMed equ kE2BT+120 +kQuad equ kE2BT+121 +kClrLst equ kE2BT+122 +kHist equ kE2BT+123 +kXYLine equ kE2BT+124 +kScatter equ kE2BT+125 +kLR1 equ kE2BT+126 +kClrTbl equ kE2BT+127 +kE2BT_end equ kClrTbl +; +; + +; new 2 byte keys + +kE2BT2 EQU 0 + +kGDB1 EQU kE2BT2 +kGDB2 EQU kE2BT2+1 +kGDB3 EQU kE2BT2+2 +kY1 EQU kE2BT2+3 +kY2 EQU kE2BT2+4 +kY3 EQU kE2BT2+5 +kY4 EQU kE2BT2+6 +kY5 EQU kE2BT2+7 +kY6 EQU kE2BT2+8 +kY7 EQU kE2BT2+9 +kY8 EQU kE2BT2+10 +kY9 EQU kE2BT2+11 +kY0 EQU kE2BT2+12 +kX1T EQU kE2BT2+13 +kY1T EQU kE2BT2+14 +kX2T EQU kE2BT2+15 +kY2T EQU kE2BT2+16 +kX3T EQU kE2BT2+17 +kY3T EQU kE2BT2+18 +kX4T EQU kE2BT2+19 +kY4T EQU kE2BT2+20 +kX5T EQU kE2BT2+21 +kY5T EQU kE2BT2+22 +kX6T EQU kE2BT2+23 +kY6T EQU kE2BT2+24 +kR1 EQU kE2BT2+25 +kR2 EQU kE2BT2+26 +kR3 EQU kE2BT2+27 +kR4 EQU kE2BT2+28 +kR5 EQU kE2BT2+29 +kR6 EQU kE2BT2+30 +kGDB4 EQU kE2BT2+31 +kGDB5 EQU kE2BT2+32 +kGDB6 EQU kE2BT2+33 +kPic4 EQU kE2BT2+34 +kPic5 EQU kE2BT2+35 +kPic6 EQU kE2BT2+36 +kGDB7 EQU kE2BT2+37 +kGDB8 EQU kE2BT2+38 +kGDB9 EQU kE2BT2+39 +kGDB0 EQU kE2BT2+40 +kPic7 EQU kE2BT2+41 +kPic8 EQU kE2BT2+42 +kPic9 EQU kE2BT2+43 +kPic0 EQU kE2BT2+44 +kStatN EQU kE2BT2+45 +kXMean EQU kE2BT2+46 +;kconj equ kE2BT2+47 +;kreal equ kE2BT2+48 +;kfangle equ kE2BT2+49 +kLCM equ kE2BT2+50 +kGCD equ kE2BT2+51 +kRandInt equ kE2BT2+52 +kCoin equ kE2BT2+53 +kDice equ kE2BT2+54 +kRemainder equ kE2BT2+55 +kYMean equ kE2BT2+56 +kStdX equ kE2BT2+57 +kStdX1 equ kE2BT2+58 +kw0 equ kE2BT2+59 +kMatf equ kE2BT2+60 +kMatg equ kE2BT2+61 +kMatrh equ kE2BT2+62 +kMati equ kE2BT2+63 +kMatj equ kE2BT2+64 +kYMean1 equ kE2BT2+65 +kStdY equ kE2BT2+66 +kStdY1 equ kE2BT2+67 +kMaTtoLst equ kE2BT2+68 +kLstToMat equ kE2BT2+69 +kCumSum equ kE2BT2+70 +kDeltaLst equ kE2BT2+71 +kStdDev equ kE2BT2+72 +kVariance equ kE2BT2+73 +kLength equ kE2BT2+74 +kEquToStrng equ kE2BT2+75 +kStrngToEqu equ kE2BT2+76 +kExpr equ kE2BT2+77 +kSubStrng equ kE2BT2+78 +kInStrng equ kE2BT2+79 +kStr1 equ kE2BT2+80 +kStr2 equ kE2BT2+81 +kStr3 equ kE2BT2+82 +kStr4 equ kE2BT2+83 +kStr5 equ kE2BT2+84 +kStr6 equ kE2BT2+85 +kStr7 equ kE2BT2+86 +kStr8 equ kE2BT2+87 +kStr9 equ kE2BT2+88 +kStr0 equ kE2BT2+89 +kSimpFact equ kE2BT2+90 +kPictPlot equ kE2BT2+91 +kCirclePlot equ kE2BT2+92 +kStemPlot equ kE2BT2+93 +kBarPlot equ kE2BT2+94 +kSumX equ kE2BT2+102 +kSumX2 equ kE2BT2+103 + +kSumY equ kE2BT2+104 +kXRes equ kE2BT2+105 + +kSumY2 equ kE2BT2+106 +kSumXY equ kE2BT2+107 +kuXRes equ kE2BT2+108 +kModBox equ kE2BT2+109 +kNormProb equ kE2BT2+110 + +kMinY equ kE2BT2+111 ; miny +kRef equ kE2BT2+112 +kRRef equ kE2BT2+113 +kLRSqr equ kE2BT2+114 +kBRSqr equ kE2BT2+115 +kDiagOn equ kE2BT2+116 +kDiagOff equ kE2BT2+117 +;kun1 equ kE2BT2+152 ; for rcl use when gotten from 82 +;kvn1 equ kE2BT2+153 ; for rcl use when gotten from 82 +kE2BT2_end equ kDiagOff + +;================================================= +; context equates +;================================================= +cxCmd equ kQuit ;home screen +cxAppsApp equ kChkApps ;apps usage screen +cxPrgmEdit equ kPrgmEd ;program editor +cxEquEdit equ kYequ ;equation editor +cxGrRange equ kWindow ;graph range editor +cxGrZfact equ kZFactEd ;graph zoom factors editor +cxGraph equ kGraph ;graph mode +cxStatEdit equ kStatEd ;statistics list editor +cxPrgmInput equ kPrgmInput ;programmed input +cxError equ kError ;error handler +cxLinkIO equ kLinkIO ;link i/o interface +cxMem equ kResetMem ;reset memory +cxDefMem equ kResetDef ;reset default +cxRAMApp equ kChkRAM ;ram usage screen +cxMode equ kMode ;mode settings screen +cxErase equ kDelMem ;memory erase +cxPrgmCreate equ kPrgmCr ;program create +cxTableEditor equ kTable ;table editor +cxTableSet equ kTblSet ;table set up +cxStatPlot equ kStatP ;stat plots +cxFormat equ kFormat ;format context +cxSolveRoot equ kSolveRoot ;solve root +cxextapps equ kExtApps ;053h ; extra applications. new +cxConstEd equ kConstEd ;056h ; constant equ editor. +cxPrgmSetVar equ kPrgmSetVar ;057h ; setmenu in a program. + +;============================================ +; scan code equates +;============================================ + +skDown EQU #01 +skLeft EQU #02 +skRight EQU #03 +skUp EQU #04 +skEnter EQU #09 +skAdd EQU #0A +skSub EQU #0B +skMul EQU #0C +skDiv EQU #0D +skConst equ #0e +skClear equ #0f +skChs equ #11 +sk3 equ #12 +sk6 equ #13 +sk9 equ #14 +skRParen equ #15 +skMixSimp equ #16 +skAppsMenu equ #17 +skDecPnt equ #19 +sk2 equ #1a +sk5 equ #1b +sk8 equ #1c +skLParen equ #1d +skFracDec equ #1e +skPrgm equ #1f +skStatEd equ #20 +sk0 equ #21 +sk1 equ #22 +sk4 equ #23 +sk7 equ #24 +skPercent equ #25 +skFracSlash equ #26 +skExpon equ #27 +skDraw equ #28 +skStore equ #2a +skComma equ #2b +skVarX equ #2c +skSimp equ #2d +skUnit equ #2e +skSquare equ #2f +skMath equ #30 +skGraph equ #31 +skTrace equ #32 +skZoom equ #33 +skWindow equ #34 +skYEqu equ #35 +sk2nd equ #36 +skMode equ #37 +skDel equ #38 + +;========================================== +; tokens +;========================================== + +EOSSTART EQU 0 +; +; +; DISPLAY CONVERSIONS COME IMMEDIATELY BEFORE 'TSTORE' +; +DCONV EQU 01h +; +tToDMS EQU DCONV ; 01h +tToDEC EQU DCONV+1 ; 02h +tToAbc EQU DCONV+2 ; 03h > A b/c +tUnredF equ 03h ;down arrow for unreduced fraction token + +tStore EQU DCONV+3 ; 04h Lstore 01 +; +tBoxPlot EQU 05h +; +BRACKS EQU 06h +; +tLBrack EQU BRACKS ; 06h '[' +tRBrack EQU BRACKS+1 ; 07h ']' +tLBrace EQU BRACKS+2 ; 08h '{' +tRBrace EQU BRACKS+3 ; 09h '}' + +tPOST1 EQU BRACKS+4 +; +tFromRad EQU tPOST1 ; 0Ah Lradian +tFromDeg EQU tPOST1+1 ; 0Bh Ldegree +tRecip EQU tPOST1+2 ; 0Ch Linverse +tSqr EQU tPOST1+3 ; 0Dh Lsquare +tTrnspos EQU tPOST1+4 ; 0Eh Ltranspose +tCube EQU tPOST1+5 ; 0Fh '^3' +; +tLParen EQU #10 ; 10h '(' +tRParen EQU #11 ; 11h ')' + +; immediate unary tokens go from here to 'eosel-1' +; +IMUN EQU #12 +; +tRound EQU IMUN ; 12h 'round' +tPxTst EQU IMUN+1 ; 13h 'PXL-TEST' +tAug EQU IMUN+2 ; 14h 'aug' +tRowSwap EQU IMUN+3 ; 15h 'rSwap' +tRowPlus EQU IMUN+4 ; 16h 'rAdd' +tmRow EQU IMUN+5 ; 17h 'multR' +tmRowPlus EQU IMUN+6 ; 18h 'mRAdd' +tMax EQU IMUN+7 ; 19h 'max' +tMin EQU IMUN+8 ; 1Ah 'min' +tRToPr EQU IMUN+9 ; 1Bh 'R>Pr +tRToPo EQU IMUN+10 ; 1Ch 'R>Po +tPToRx EQU IMUN+11 ; 1Dh 'P>Rx +tPToRy EQU IMUN+12 ; 1Eh 'P>Ry +tMedian EQU IMUN+13 ; 1Fh 'MEDIAN +tRandM EQU IMUN+14 ; 20h 'randM' +tMean EQU IMUN+15 ; 21h +tLstMode equ IMUN+16 ; 22h 'mode(' +;the below tokens are immediate, but require an expression as 1st arg & so +;are grouped together... +tRoot equ IMUN+17 ; 23h 'solve(' +tSeries equ IMUN+18 ; 24h 'seq' +tEvalF equ IMUN+20 ; 26h ;keep until sure. +IMUNEND equ IMUN+20 ;end of immediate unaries. + +tSolveEqual equ IMUN+21 ;teq ('=') in solver -> tsolveequal. +tEOFrac equ IMUN+22 ; 28h end of fraction in home screen. +; +; +; token 29h cannot be an eos function since el(=29h already +; +tEOSEL EQU IMUN+23 +; +tSpace EQU tEOSEL ; 29h ' ' +tString EQU tEOSEL+1 ; 2Ah '"' +tComma EQU tEOSEL+2 ; 2Bh ',' +tRemain equ 2ch ;'r' for remainder display. +; tremain is needed in home screen where turn display chars into tokens. +; (there is no token for small 'r'). +; ===== postfix functions +; +tPost equ #2e +; +tFact equ tPost ; 2eh '!' +tPercent equ tPost+1 ; 2fh '%' new + +;=============number tokens + +NUMS EQU 30h +; +t0 EQU NUMS ; 30h +t1 EQU NUMS+1 ; 31h +t2 EQU NUMS+2 ; 32h +t3 EQU NUMS+3 ; 33h +t4 EQU NUMS+4 ; 34h +t5 EQU NUMS+5 ; 35h +t6 EQU NUMS+6 ; 36h +t7 EQU NUMS+7 ; 37h +t8 EQU NUMS+8 ; 38h +t9 EQU NUMS+9 ; 39h +tDecPt EQU NUMS+10 ; 3Ah +tee EQU NUMS+11 ; 3Bh + +;======================= +; binary op +;======================= +tOr EQU #3C ; 3Ch '_or_' +tXor EQU #3D ; 3Dh +; +tColon EQU #3E ; 3Eh ':' +tEnter EQU #3F ; 3Fh Lenter +; +tAnd EQU #40 ; 40h '_and_' + +;======================== +; letter tokens +;======================== +LET EQU #41 +; +tA EQU LET ; 41h +tB EQU LET+1 ; 42h +tC EQU LET+2 ; 43h +tD EQU LET+3 ; 44h +tE EQU LET+4 ; 45h +tF EQU LET+5 ; 46h +tG EQU LET+6 ; 47h +tH EQU LET+7 ; 48h +tI EQU LET+8 ; 49h +tJ EQU LET+9 ; 4Ah +tK EQU LET+10 ; 4Bh +tL EQU LET+11 ; 4Ch +tM EQU LET+12 ; 4Dh +tN EQU LET+13 ; 4Eh +tO EQU LET+14 ; 4Fh +tP EQU LET+15 ; 50h +tQ EQU LET+16 ; 51h +tR EQU LET+17 ; 52h +tS EQU LET+18 ; 53h +tT EQU LET+19 ; 54h +tU EQU LET+20 ; 55h +tV EQU LET+21 ; 56h +tW EQU LET+22 ; 57h +tX EQU LET+23 ; 58h +tY EQU LET+24 ; 59h +tZ EQU LET+25 ; 5Ah +tEOF equ LET+26 ; 5bh +; +;=============================================== +; these var tokens are 1st of a double token +;=============================================== +; +;====================================================================== +; THESE VAR TOKENS ARE 1ST OF A DOUBLE TOKEN +;====================================================================== + +; +vToks EQU LET+27 ; +; +; USER MATRIX TOKEN, 2ND TOKEN NEEDED FOR NAME +; +tVarMat EQU vToks ; 5Ch +; +; USER LIST TOKEN, 2ND TOKEN NEEDED FOR NAME +; +tVarLst EQU vToks+1 ; 5Dh +; +; USER EQUATION TOKEN, 2ND TOKEN NEEDED FOR NAME +; +tVarEqu EQU vToks+2 ; 5Eh +tProg EQU vToks+3 ; 5Fh +; +; USER PICT TOKEN, 2ND TOKEN NEEDED FOR NAME +; +tVarPict EQU vToks+4 ; 60h +; +; USER GDB TOKEN, 2ND TOKEN NEEDED FOR NAME +; +tVarGDB EQU vToks+5 ; 61h +tVarOut EQU vToks+6 ; 62h +tVarSys EQU vToks+7 ; 63h + +;================================ +; ===== mode setting commands +;================================ +MODESA EQU vToks+8 ; 64h +; +tRad EQU MODESA ; 64h 'Radian' +tDeg EQU MODESA+1 ; 65h 'Degree' +tNormF EQU MODESA+2 ; 66h 'Normal' +tSci EQU MODESA+3 ; 67h 'Sci' +tEng EQU MODESA+4 ; 68h 'Eng' +tFloat EQU MODESA+5 ; 69h 'Float' +; +CMPS EQU #6A +; +tEQ EQU CMPS ; 6Ah '==' +tLT EQU CMPS+1 ; 6Bh '<' +tGT EQU CMPS+2 ; 6Ch '>' +tLE EQU CMPS+3 ; 6Dh LLE +tGE EQU CMPS+4 ; 6Eh LGE +tNE EQU CMPS+5 ; 6Fh LNE + +;======================= +; binary op +;======================= +tAdd equ #70 ; 70h '+' +tSub equ #71 ; 71h '-' +; +tAns equ #72 ; 72h +; +;============================ +;===== mode setting commands +;============================ +; graph format tokens are 2 byte tokens +; +tGFormat equ #73 +; +; +tBoyIcon equ #78 ; for stat plots in programs +tTreeIcon equ #79 ; for stat plots in programs +tDollarIcon equ #7a ; for stat plots in programs +tFaceIcon equ #7b ; for stat plots in programs +tCircleIcon equ #7c ; for stat plots in programs +tDiamondIcon equ #7d ; for stat plots in programs +tStarIcon equ #7e ; for stat plots in programs +tBoxIcon equ #7f +tCrossIcon equ #80 +tDotIcon equ #81 +; +;=========================== +; binary op cont. +;=========================== +tMul equ #82 ; 82h '*' +tDiv equ #83 ; 83h '/' +tIDiv equ #84 ; 84h 'int/' +; +;============================ +; some graph commands +;============================ +; +GRCMDS equ 85h +; +tTrace EQU GRCMDS ; 84h 'Trace' +tClDrw EQU GRCMDS+1 ; 85h 'ClDrw' +tZoomStd EQU GRCMDS+2 ; 86h 'ZStd' +tZoomtrg EQU GRCMDS+3 ; 87h 'Ztrg' +tZoomBox EQU GRCMDS+4 ; 88h 'ZBOX' +tZoomIn EQU GRCMDS+5 ; 89h 'ZIn' +tZoomOut EQU GRCMDS+6 ; 8Ah 'ZOut' +tZoomSqr EQU GRCMDS+7 ; 8Bh 'ZSqr' +tZoomInt EQU GRCMDS+8 ; 8Ch 'ZInt' +tZoomPrev EQU GRCMDS+9 ; 8Dh 'ZPrev' +tZoomDec EQU GRCMDS+10 ; 8Eh 'ZDecm' +tZoomStat EQU GRCMDS+11 ; 8Fh 'ZStat +tZoomQuad1 equ GRCMDS+12 ; 91h 'quadrant 1' +tZoomSto equ GRCMDS+14 ; 93h zoom store +tText equ GRCMDS+15 ; 94h +; +;======================= +; binary op +;======================= +tnPr EQU GRCMDS+16 ; 94h '_nPr_' +tnCr EQU GRCMDS+17 ; 95h '_nCr_' + +;========================================================================= +; more graph commands (start of graph commands requiring arguments) +;========================================================================= + +tYOn EQU GRCMDS+18 ; 96h 'FnOn_' +tYOff EQU GRCMDS+19 ; 97h 'FnOff_' +tStPic EQU GRCMDS+20 ; 98h 'StPic_' +tRcPic EQU GRCMDS+21 ; 99h 'RcPic_' +tLine EQU GRCMDS+22 ; 9bh 'line' +tVert EQU GRCMDS+23 ; 9ch 'vert_' +tPtOn EQU GRCMDS+24 ; 9dh 'pton' +tPtOff EQU GRCMDS+25 ; 9eh 'ptoff' +; +;=============================================================== +; token a0 cannot be an eos function since low mult=a0 already +;=============================================================== +tPtChg EQU GRCMDS+26 ; 9fh 'ptchg' +tPXOn EQU GRCMDS+27 ; a0h +tPXOff EQU GRCMDS+28 ; a1h +tPXChg EQU GRCMDS+29 ; a2h +tShade EQU GRCMDS+30 ; a3h 'shade' +tCircl EQU GRCMDS+31 ; a4h 'circl' +tHorz EQU GRCMDS+32 ; a5h 'horizontal' +tTanLn EQU GRCMDS+33 ; a6h 'tanln' +;tManFit equ GRCMDS+34 ; a7h 'manual fit' + +; +;available equ GRCMDS+35 ; a8h +; +tDrInv equ GRCMDS+36 ; a9h 'drinv_' +tDrawF equ GRCMDS+36 ; a9h 'drawf_' +; +tVarStrng equ 0aah +; +;=================================== +; ===== functions with no arguments +;=================================== +; +NOARG EQU 0ABh +; +tRand EQU NOARG ; ABh 'rand' +tPi EQU NOARG+1 ; ACh Lpi +tGetKey EQU NOARG+2 ; ADh 'getKy' +; +; +tAPost EQU tGetKey+1 ; APOSTROPHY +tQuest EQU tAPost+1 ; QUESTION MARK +; +; +UNARY EQU tQuest+1 ; B0h +; +tChs EQU UNARY ; B0h +tInt EQU UNARY+1 ; B1h +tAbs EQU UNARY+2 ; B2h +tDet EQU UNARY+3 ; B3h +tIdent EQU UNARY+4 ; B4h +tDim EQU UNARY+5 ; B5h +tSum EQU UNARY+6 ; B6h +tProd EQU UNARY+7 ; B7h +;tUnit EQU UNARY+8 ; B8h +tIPart EQU UNARY+9 ; B9h +tFPart EQU UNARY+10 ; BAh +; +;================================ +; new 2 byte tokens +;================================ +t2ByteTok equ #0bb ; +; +; +UNARYLR EQU UNARY+12 +; +tSqrt EQU UNARYLR ; BCh +tCubRt EQU UNARYLR+1 ; BDh +tLn EQU UNARYLR+2 ; BEh +tExp EQU UNARYLR+3 ; BFh +tLog EQU UNARYLR+4 ; C0h +tALog EQU UNARYLR+5 ; C1h +tSin EQU UNARYLR+6 ; C2h +tASin EQU UNARYLR+7 ; C3h +tCos EQU UNARYLR+8 ; C4h +tACos EQU UNARYLR+9 ; C5h +tTan EQU UNARYLR+10 ; C6h +tATan EQU UNARYLR+11 ; C7h +LASTUNARY2 equ UNARYLR+11 ; c7h +tMixSimp equ UNARYLR+12 ;c8convert between mixed(ab/c) & simple(b/c) +tFracDec equ UNARYLR+13 ;c9h convert between fraction & decimal. +tSimp equ UNARYLR+14 ;cah simplify a fraction. + +;================= +; binary op +;================= +tPower equ #0cb ; cbh '^' +tXRoot equ #0cc ; cch lsupx,lroot + +;=================================== +; some programming commands +;=================================== +; +PROGTOK equ UNARYLR+17 +; +tSetMenu equ PROGTOK ; cdh +tIf equ PROGTOK+1 ; ceh +tThen equ PROGTOK+2 ; cfh +tElse equ PROGTOK+3 ; d0h +tWhile equ PROGTOK+4 ; d1h +tRepeat equ PROGTOK+5 ; d2h +tFor equ PROGTOK+6 ; d3h +tEnd equ PROGTOK+7 ; d4h +tReturn equ PROGTOK+8 ; d5h +tLbl equ PROGTOK+9 ; d6h 'lbl_' +tGoto equ PROGTOK+10 ; d7h 'goto_' +tPause equ PROGTOK+11 ; d8h 'pause_' +tStop equ PROGTOK+12 ; d9h 'stop' +tISG equ PROGTOK+13 ; dah 'is>' +tDSL equ PROGTOK+14 ; dbh 'ds<' +tInput equ PROGTOK+15 ; dch 'input_' +tPrompt equ PROGTOK+16 ; ddh 'prompt_' +tDisp equ PROGTOK+17 ; deh 'disp_' +tDispG equ PROGTOK+18 ; dfh 'dispg' +; +tOutput equ PROGTOK+19 ; e0h 'outpt' +tClLCD equ PROGTOK+20 ; e1h 'cllcd' +tFill equ PROGTOK+21 ; e2h 'fill' +tSortA equ PROGTOK+22 ; e3h 'sorta_' +tSortD equ PROGTOK+23 ; e4h 'sortd_' +tDispTab equ PROGTOK+24 ; e5h 'disp table +tMenu equ PROGTOK+25 ; e6h 'menu' +tSendMBL equ PROGTOK+26 ; e7h 'send' +tGetMBL equ PROGTOK+27 ; e8h 'get' +; +;=================================== +; stat plot commands +;=================================== +statPCmd equ PROGTOK+28 +; +tPlotOn equ statPCmd ; e9h ' plotson' +tPlotOff equ statPCmd+1 ; eah ' plotsoff +CmdLen0 equ tPlotOff - PROGTOK+ 1 +CmdOff1 equ CmdLen0 - 1 +; +tListName equ #0eb ; list designator +; +tPlot1 equ #0ec +tPlot2 equ #0ed +tPlot3 equ #0ee + +tUnit equ #0ef ; efh unit for mixed fractions (a u b/c) +tFracSlash equ #0f0 ; f0h '/' (bc symbol) + +tStatCmd equ #0f2 +; +;================================== +; 2nd half of graph format tokens +; +; ===== format settings commands +;=================================== + +GFMT equ 1 +; +tSeq equ GFMT ; 01 'seqg' +tSimulG equ GFMT+1 ; 02 'simulg' +tCoordOn equ GFMT+2 ; 03 'coordon' +tCoordOff equ GFMT+3 ; 04 'coordoff' +tDrawLine equ GFMT+4 ; 05 'drawline' +tDrawDot equ GFMT+5 ; 06 'drawdot' +tAxisOn equ GFMT+6 ; 07 'axeson' +tAxisOff equ GFMT+7 ; 08 'axesoff' +tGridOn equ GFMT+8 ; 09 'gridon' +tGridOff equ GFMT+9 ; 0a 'gridoff' +tLblOn equ GFMT+10 ; 0b 'labelon' +tLblOff equ GFMT+11 ; 0c 'labeloff' +tPolarG equ GFMT+12 ; 0d 'polargc' +tRectG equ GFMT+13 ; 0e 'rectgc' +; +;===================================== +; 2nd half of mode setting tokens +;===================================== +MODES2 equ GFMT+14 +; +tStndrd equ MODES2 ; 0fh 'func' +tParam equ MODES2+1 ; 10h 'param' +tPolar equ MODES2+2 ; 11h 'pol' +tAFillOn equ MODES2+3 ; 12h 'auto fill on +tAFillOff equ MODES2+4 ; 13h +tACalcOn equ MODES2+5 ; 14h +tACalcOff equ MODES2+6 ; 15h 'autofill off +; +tMABC equ MODES2+7 ; 16h 'aub/c mode' +tMBC equ MODES2+8 ; 17h 'b/c mode' +tMAutoSimp equ MODES2+9 ; 18h 'b/c mode' +tMManSimp equ MODES2+10 ; 19h 'b/c mode' +tMSingleC equ MODES2+11 ; 1ah single constant +tMMultiC equ MODES2+12 ; 1bh multi constant + + +STATREGS equ 1 +tOneVar equ STATREGS ; 01h 'onevar_' +tTwoVar equ STATREGS+1 ; 02h +tLR1 equ STATREGS+2 ; 03h 'linr(ax+b +tManFit equ STATREGS+5 ; 07h 'manual fit' +tMedMed equ STATREGS+6 ; 08h +tQuad equ STATREGS+7 ; 09h +tClrLst equ STATREGS+8 ; 0ah 'clear list +tClrTbl equ STATREGS+9 ; 0bh clear table +tHist equ STATREGS+10 ; 0ch 'hist_' +tXYLine equ STATREGS+11 ; 0dh 'xyline_' +tScatter equ STATREGS+12 ; 0eh 'scatter_' +tLR equ STATREGS+13 ; 0fh 'linr(a+bx + +;====================================== +; 2nd half of user list tokens +;====================================== +tL1 equ #01 ; list 1 +tL2 equ #02 ; list 2 +tL3 equ #03 ; list 3 +tL4 equ #04 ; list 4 +tL5 equ #05 ; list 5 +tL6 equ #06 ; list 6 + +;=========================================== +; 2nd half of user equation tokens +;=========================================== +; +tY1 equ #10 ; y1 +tY2 equ #11 ; y2 +tY3 equ #12 ; y3 +tY4 equ #13 ; y4 +; +; constant equations have bit 7 set +tC1 equ #80 ; const1 +tC2 equ #81 ; const2 +tC3 equ #82 ; const3 +tC4 equ #83 ; const4 +; +;=========================================== +; 2nd half of user picture tokens +;=========================================== +tPic1 equ #01 ; pic1 +tPic2 equ #02 ; pic2 +tPic3 equ #03 ; pic3 + +;============================================== +; 2nd half of user graph database tokens +;============================================== +tGDB1 equ #01 ; gdb1 +tGDB2 equ #02 ; gdb2 +tGDB3 equ #03 ; gdb3 +tGDB4 equ #04 ; gdb4 +tGDB5 equ #05 ; gdb5 +tGDB6 equ #06 ; gdb6 +tGDB7 equ #07 ; gdb7 +tGDB8 equ #08 ; gdb8 +tGDB9 equ #09 ; gdb9 +tGDB0 equ #0a ; gdb0 +; +;==================================== +; 2nd half of string vars +;==================================== +tStr1 equ #01 +tStr2 equ #02 +tStr3 equ #03 +tStr4 equ #04 +tStr5 equ #05 +tStr6 equ #06 +tStr7 equ #07 +tStr8 equ #08 +tStr9 equ #09 +tStr0 equ #0a + +;================================================== +; 2nd half of system output only variables +;================================================== +; +; OPEN EQU #00 +; +tRegEq EQU #01 ; REGRESSION EQUATION +; +tStatN EQU #02 ; STATISTICS N +; +tXMean EQU #03 ; X MEAN +tSumX EQU #04 ; SUM(X) +tSumXSqr EQU #05 ; SUM(X^2) +tStdX EQU #06 ; STANDARD DEV X +tStdPX EQU #07 ; STANDARD DEV POP X +tMinX EQU #08 ; Min X VALUE +tMaxX EQU #09 ; Max X VALUE +; +tMinY EQU #0A ; Min Y VALUE +tMaxY EQU #0B ; Max Y VALUE +tYmean EQU #0C ; Y MEAN +tSumY EQU #0D ; SUM(Y) +tSumYSqr EQU #0E ; SUM(Y^2) +tStdY EQU #0F ; STANDARD DEV Y +tStdPY EQU #10 ; STANDARD DEV POP Y +; +tSumXY EQU #11 ; SUM(XY) +tCorr EQU #12 ; CORRELATION +tMedX EQU #13 ; MED(X) +tQ1 EQU #14 ; 1ST QUADRANT OF X +tQ3 EQU #15 ; 3RD QUADRANT OF X +tQuadA EQU #16 ; 1ST TERM OF QUAD POLY REG/ Y-INT +tQuadB EQU #17 ; 2ND TERM OF QUAD POLY REG/ SLOPE +tQuadC EQU #18 ; 3RD TERM OF QUAD POLY REG +tCubeD EQU #19 ; 4TH TERM OF CUBIC POLY REG +tQuartE EQU #1A ; 5TH TERM OF QUART POLY REG +tMedX1 EQU #1B ; x1 FOR MED-MED +tMedX2 EQU #1C ; x2 FOR MED-MED +tMedX3 EQU #1D ; x3 FOR MED-MED +tMedY1 EQU #1E ; y1 FOR MED-MED +tMedY2 EQU #1F ; y2 FOR MED-MED +tMedY3 EQU #20 ; y3 FOR MED-MED +; +tLRSqr equ #21 ; r^2 +tBRSqr equ #22 ; r^2 +; +tError equ #23 ; token in case of error in entry (ans only) +tDone equ #24 +; +;==================================== +; system variable equates +; vars with no restriction +;==================================== +tuXscl equ 1 +tuYscl equ 2 +tXscl equ 3 +tYscl equ 4 + +tXmin EQU #0A +tXmax EQU #0B +tYmin EQU #0C +tYmax EQU #0D +tTmin EQU #0E +tTmax EQU #0F +tThetaMin EQU #10 +tThetaMax EQU #11 +tuXmin EQU #12 +tuXmax EQU #13 +tuYmin EQU #14 +tuYmax EQU #15 +tuThetMin EQU #16 +tuThetMax EQU #17 +tuTmin EQU #18 +tuTmax EQU #19 +tTblMin EQU #1A +tPlotStart EQU #1B +tuPlotStart EQU #1C +tnMax EQU #1D +tunMax EQU #1E +tnMin EQU #1F +tunMin EQU #20 + +; +; vars cannot be 0 +; +tTblStep equ #21 +tTStep equ #22 +tThetaStep equ #23 +tuTStep equ #24 +tuThetStep equ #25 +; +; special limits on these +; +tDeltaX equ #26 +tDeltaY equ #27 +; +; special limits on these +; +tXFact equ #28 +tYFact equ #29 +; +tTblInput equ #2a +; +; no restrictions +tSimpFact equ #2b ;simplification factor. +; +tPlotStep equ #34 +tuPlotStep equ #35 +; +tXres equ #36 +tuXres equ #37 +; + +;====================================== +;2nd byte of 2byte tokens +;====================================== + +tLCM equ #01 ; immediate unary +tGCD equ #02 ; immediate unary +tRandInt equ #03 ; immediate unary +tSubStrng equ #04 ; immediate unary +tStdDev equ #05 ; immediate unary +tVariance equ #06 ; immediate unary +tInStrng equ #07 ; immediate unary +tCoin equ #08 ; immediate unary +tDice equ #09 ; immediate unary +tRemainder equ #0a ; immediate unary +lastImUnary equ #0a ; last immediate unary token. +firstUnary equ #0b ; first unary operator. +tCumSum equ #0b ; unary +tExpr equ #0c ; unary do autop +tLength equ #0d ; unary do autop +tDeltaLst equ #0e ; unary do autop +tRef equ #0f ; unary no autop +autoP10 equ #10 +tRRef equ #10 ; unary no autop +newTok12 equ #12 + +autoP11 equ #12 +tMatToLst equ #12 ; command pushed do autop +tLstToMat equ #13 ; command pushed do autop +tSetConst equ #14 ; autop +tGraphStyle equ #15 ; command pushed autop +autoP12 equ #15 +tSetUpLst equ #16 ; command opt pushed no autop +tExprOn equ #1a ; mode command +tExprOff equ #1b ; mode command +tClrSllLst equ #1c ; command not pushed +tGetCalc equ #1d ; command not pushed +tDelVar equ #1e ; command not pushed +tEquToStrng equ #1f ; command not pushed +tStrngToEqu equ #20 ; command not pushed +tDelLast equ #21 ; command not pushed +tSelect equ #22 ; command not pushed +tModBox equ #23 ; icon +tNormProb equ #24 ; icon +tPictOlot equ #25 +tCirclePlot equ #26 +tStemPlot equ #27 +tBarPlot equ #28 +tZFit equ #29 ; zoom fit +tDiag_On equ #2a ; dianostic display on +tDiag_Off equ #2b ; dianostic display off + +;========================================== +; data type equates +;=========================================== +RealObj equ 0 +ListObj equ 1 +MatObj equ 2 +EquObj equ 3 +StrngObj equ 4 +ProgObj equ 5 +ProtProgObj equ 6 +PictObj equ 7 +GDBObj equ 8 +UnknownObj equ 9 +UnknownEquObj equ #0a +NewEquObj equ #0b +CplxObj equ #0c +ClistObj equ #0d +SlistObj equ #0d ;string list +UndefObj equ #0e +WindowObj equ #0f +ZStoObj equ #10 +TblrngObj equ #11 +LCDObj equ #12 +BackupObj equ #13 +FracObj equ #14 +FracRSObj equ #14 ;reduced simple fraction. +FracRMObj equ #15 ;reduced mixed fraction. +FracUSObj equ #16 ;unreduced simple fraction. +FracUMObj equ #17 ;unreduced mixed fraction. +NameObj equ #18 ;name string (will fit in fplen). +AppObj equ #19 ;application, only used in menus/link +AppVarObj equ #1a ;application variable +TmpConstObj equ #1b ;temporary type of constant. + +;====================================================================== +; i/o equates +;====================================================================== +; +D0D1_bits EQU #03 +D0LD1L EQU #03 +D0LD1H EQU #01 +D0HD1L EQU #02 +D0HD1H EQU #00 +bport EQU 0 ; 4-BIT LINK PORT (I/O) +; +;====================================================================== +; device codes +;====================================================================== +; +; +TI82DEV EQU #82 +PC82DEV EQU #02 +MAC82DEV EQU #12 +; +LINK83FDEV EQU #23 +; +TI83DEV EQU #83 +PC83DEV EQU #03 +MAC83DEV EQU #13 +; +TI85DEV EQU #95 ; DIFF THEN REAL 85 SO ME TALK +PC85DEV EQU #05 +MAC85DEV EQU #15 +; +TI73DEV EQU #74 ; Device x3 is always an 83 +PC73DEV EQU #07 +MAC73DEV EQU #17 +; +TI83FDEV EQU #73 +LINK73FDEV EQU #23 +PC83FDEV EQU #23 + +;========================================= +; system error codes +;========================================= + +E_EDITF EQU 7 ;allow re-entering application +E_EDIT EQU 1< current home-screen input +BYTES_USED EQU $80CC ; # of used user memory (Add to 80C8 to find first + ; byte of free memory) +TEXT_MEM EQU $80DF ; text memory +CURSOR_ROW2 EQU $800C ; text cursor row +CURSOR_COL2 EQU $800D ; text cursor column +CHECKSUM EQU $81BE ; memory checksum from 8BF7 to FA6F +CURSOR_X EQU $8333 ; x value of cursor +CURSOR_Y EQU $8334 ; y value of cursor +_IY_TABLE EQU $8346 ; where IY usually points +GRAPH_MEM EQU $8641 ; graphics memory +TEXT_MEM2 EQU $8A6B ; secondary text memory +USER_MEM EQU $8B1B ; -> start of user memory +FIXED_POINT EQU $8B3A ; fixed-point decimal place (FFh for floating point) +VAT_END EQU $8BEB ; -> one byte before end of VAT (backwards) +VAT_START EQU $FA6F ; start of VAT +VIDEO_MEM EQU $FC00 ; video memory +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Keypad Scancodes ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; Function Character +K_NOKEY EQU $00 ;No key +K_DOWN EQU $01 ;Down +K_LEFT EQU $02 ;Left +K_RIGHT EQU $03 ;Right +K_UP EQU $04 ;Up +K_ENTER EQU $09 ;Enter +K_PLUS EQU $0A ;+ X +K_MINUS EQU $0B ;- T +K_STAR EQU $0C ;* O +K_SLASH EQU $0D ;/ J +K_RAISE EQU $0E ;^ E +K_CLEAR EQU $0F ;Clear +K_SIGN EQU $11 ;(-) Space +K_3 EQU $12 ;3 W +K_6 EQU $13 ;6 S +K_9 EQU $14 ;9 N +K_RIGHTPAR EQU $15 ;) I +K_TAN EQU $16 ;Tan D +K_CUSTOM EQU $17 ;Custom +K_DOT EQU $19 ;. Z +K_2 EQU $1A ;2 V +K_5 EQU $1B ;5 R +K_8 EQU $1C ;8 M +K_LEFTPAR EQU $1D ;( H +K_COS EQU $1E ;Cos C +K_PRGM EQU $1F ;Prgm +K_DEL EQU $20 ;Del +K_0 EQU $21 ;0 Y +K_1 EQU $22 ;1 U +K_4 EQU $23 ;4 Q +K_7 EQU $24 ;7 L +K_EE EQU $25 ;EE G +K_SIN EQU $26 ;Sin B +K_STAT EQU $27 ;Stat +K_XVAR EQU $28 ;x-Var x +K_ON EQU $29 ;On +K_STO EQU $2A ;Sto EQU +K_COMMA EQU $2B ;, P +K_SQUARE EQU $2C ;x^2 K +K_LN EQU $2D ;Ln F +K_LOG EQU $2E ;Log A +K_GRAPH EQU $2F ;Graph +K_ALPHA EQU $30 ;Alpha +K_F5 EQU $31 ;F5 +K_F4 EQU $32 ;F4 +K_F3 EQU $33 ;F3 +K_F2 EQU $34 ;F2 +K_F1 EQU $35 ;F1 +K_SECOND EQU $36 ;2nd +K_EXIT EQU $37 ;EXIT +K_MORE EQU $38 ;MORE diff --git a/_include/old/ti73.inc b/_include/old/ti73.inc new file mode 100644 index 0000000..e69de29 diff --git a/_include/old/ti86.inc b/_include/old/ti86.inc new file mode 100644 index 0000000..21882e0 --- /dev/null +++ b/_include/old/ti86.inc @@ -0,0 +1,115 @@ + +LPON EQU $fc ;link port off +LPOFF EQU $c0 ;link port on +LPL EQU $d4 ;link port left on +LPR EQU $e8 ;link port right on +LPSW EQU $3c ;toggle link port state +LPSWL EQU %00101000 ;toggle link port state left +LPSWR EQU %00010100 ;toggle link port state right +LMSK EQU $fcfc ;link port mask +LRMASK EQU $d4e8 ;link port stereo mask +LPORT EQU 7 +KPORT EQU 1 + +progstart EQU #D748 + + org progstart + + +;==================================================================== +;These are common zshell and usgard calls that are known on the TI-86 +;If possible, use the call that is commented next to the one you want +;==================================================================== +MUL_HL EQU $4547 + +CP_HL_DE EQU $403C +LD_HL_MHL EQU $4010 +GET_KEY EQU $5371 +UNPACK_HL EQU $4044 + +D_HL_DECI EQU $4a33 + +BUSY_OFF EQU $4ab1 ;_runindoff +BUSY_ON EQU $4aad ;_runindicon +D_ZT_STR EQU $4a37 ;_puts +D_LT_STR EQU $4a3b ;_putps +TX_CHARPUT EQU $4a2b ;_putc +D_ZM_STR EQU $4aa5 ;_vputs +D_LM_STR EQU $4aa9 ;_vputsn +M_CHARPUT EQU $4aa1 ;_vputmap +CLEARLCD EQU $4a7e ;_clrLCD + + +;======================================================== +;These are memory addresses common for zshell programming +;If possible, use the one on the right +;======================================================== + +CONTRAST EQU $c008 +CURSOR_ROW EQU $c00f ;_curRow +CURSOR_COL EQU $c010 ;_curCol +BUSY_COUNTER EQU $c087 +BUSY_BITMAP EQU $c088 +TEXT_MEM EQU $c0f9 ;_textShadow +CURSOR_X EQU $c37c ;_penCol +CURSOR_Y EQU $c37d ;_penRow +GRAPH_MEM EQU $c9fa ;_plotSScreen +TEXT_MEM2 EQU $cfab ;_cmdShadow +VAT_END EQU $d298 +VAT_START EQU $8000 +VIDEO_MEM EQU $fc00 + +;================================================================== +;all the keys are used with , not TI's +;================================================================== +K_NOKEY EQU $00 ;No key +K_DOWN EQU $01 ;Down +K_LEFT EQU $02 ;Left +K_RIGHT EQU $03 ;Right +K_UP EQU $04 ;Up +K_ENTER EQU $09 ;Enter +K_PLUS EQU $0A ;+ X +K_MINUS EQU $0B ;- T +K_STAR EQU $0C ;* O +K_SLASH EQU $0D ;/ J +K_RAISE EQU $0E ;^ E +K_CLEAR EQU $0F ;Clear +K_SIGN EQU $11 ;(-) Space +K_3 EQU $12 ;3 W +K_6 EQU $13 ;6 S +K_9 EQU $14 ;9 N +K_RIGHTPAR EQU $15 ;) I +K_TAN EQU $16 ;Tan D +K_CUSTOM EQU $17 ;Custom +K_DOT EQU $19 ;. Z +K_2 EQU $1A ;2 V +K_5 EQU $1B ;5 R +K_8 EQU $1C ;8 M +K_LEFTPAR EQU $1D ;( H +K_COS EQU $1E ;Cos C +K_PRGM EQU $1F ;Prgm +K_DEL EQU $20 ;Del +K_0 EQU $21 ;0 Y +K_1 EQU $22 ;1 U +K_4 EQU $23 ;4 Q +K_7 EQU $24 ;7 L +K_EE EQU $25 ;EE G +K_SIN EQU $26 ;Sin B +K_TABLE EQU $27 ;Table ;Used to be Stat on the TI-85, now K_TABLE +K_XVAR EQU $28 ;x-Var x +K_ON EQU $29 ;On +K_STO EQU $2A ;Sto EQU +K_COMMA EQU $2B ;, P +K_SQUARE EQU $2C ;x^2 K +K_LN EQU $2D ;Ln F +K_LOG EQU $2E ;Log A +K_GRAPH EQU $2F ;Graph +K_ALPHA EQU $30 ;Alpha +K_F5 EQU $31 ;F5 +K_F4 EQU $32 ;F4 +K_F3 EQU $33 ;F3 +K_F2 EQU $34 ;F2 +K_F1 EQU $35 ;F1 +K_SECOND EQU $36 ;2nd +K_EXIT EQU $37 ;EXIT +K_MORE EQU $38 ;MORE diff --git a/_include/ti82.inc b/_include/ti82.inc new file mode 100644 index 0000000..73ad412 --- /dev/null +++ b/_include/ti82.inc @@ -0,0 +1,68 @@ +;********************************************************************************** +;include file for TI-82/CrASH 1.1 +;********************************************************************************** + +progstart equ #9104 ;all CrASH programs start here + + org progstart + +;********************************************************************************** +;ports + +link equ #00 ;link port +kbd equ #01 ;keyboard port +rom equ #02 ;ROM page select port +kon equ #03 ;ON key port +lcd_crt equ #10 ;lcd control port +lcd_data equ #11 ;ldc data port + +;********************************************************************************** +;link port states + +lp_on equ #fc ;link port off +lp_off equ #c0 ;link port on +lp_l equ #d4 ;link port left on +lp_r equ #e8 ;link port right on +lp_sw equ #3c ;toggle link port state +lp_swl equ #28 ;toggle link port state left +lp_swr equ #14 ;toggle link port state right +;lp_msk equ #fcfc ;link port mask +lp_msk equ #c0c0 +lp_smsk equ #d4e8 ;link port stereo mask + +;********************************************************************************** +;saferam addresses + +graph_mem equ #88b8 ;768 bytes +apd_buf equ #8228 ;768 bytes +text_mem equ #808f ;128 bytes +text_mem2 equ #8bdf ;128 bytes +ops equ #8028 ;66 bytes + +mem_end equ #fcb3 ;user memory end (excl. safety margin) + +;********************************************************************************** +;rom_call macro + +macro rom_call,addr + call #8d74 + dw addr +endm + +macro key_delay + nop + nop +endm + + +;********************************************************************************** +;rom calls + +clearlcd equ #389a ;clear LCD, but not text or graphics memory +cleartext_f equ #37A4 ;clear text_mem + +;********************************************************************************** +;shell flags + +int_state equ #8d72 ;apd_buf usage flag + diff --git a/_include/ti82parcus.inc b/_include/ti82parcus.inc new file mode 100644 index 0000000..3713aa1 --- /dev/null +++ b/_include/ti82parcus.inc @@ -0,0 +1,60 @@ +;********************************************************************************** +;include file for TI-82/CrASH 1.1 +;********************************************************************************** + +progstart equ #9104 ;all CrASH programs start here + + org progstart + +;********************************************************************************** +;ports + +link equ #00 ;link port +kbd equ #01 ;keyboard port +rom equ #02 ;ROM page select port +kon equ #03 ;ON key port +lcd_crt equ #10 ;lcd control port +lcd_data equ #11 ;ldc data port + +;********************************************************************************** +;link port states + +lp_on equ #d3 ;link port off +lp_off equ #d0 ;link port on +lp_l equ #d1 ;link port left on +lp_r equ #d2 ;link port right on +lp_sw equ #03 ;toggle link port state +lp_swl equ #01 ;toggle link port state left +lp_swr equ #02 ;toggle link port state right +;lp_msk equ #d3d3 ;link port mask +lp_msk equ #d0d0 ;link port mask +lp_smsk equ #d1d2 ;link port stereo mask + +;********************************************************************************** +;saferam addresses + +graph_mem equ #88b8 ;768 bytes +apd_buf equ #8228 ;768 bytes +text_mem equ #808f ;128 bytes +text_mem2 equ #8bdf ;128 bytes +ops equ #8028 ;66 bytes + +;********************************************************************************** +;rom_call macro + +macro rom_call,addr + call #8d74 + dw addr +endm + +;********************************************************************************** +;rom calls + +clearlcd equ #39cd ;clear LCD, but not text or graphics memory +cleartext_f equ #37A4 ;clear text_mem + +;********************************************************************************** +;shell flags + +int_state equ #8d72 ;apd_buf usage flag + diff --git a/_include/ti83.inc b/_include/ti83.inc new file mode 100644 index 0000000..4979267 --- /dev/null +++ b/_include/ti83.inc @@ -0,0 +1,69 @@ +;********************************************************************************** +;include file for TI-83/Ion 1.6 +;********************************************************************************** + +progstart equ #9327 ;all Ion programs start here + + org progstart + xor a + jr nc,begin + ret + +;********************************************************************************** +;ports + +link equ #00 ;link port +kbd equ #01 ;keyboard port +rom equ #02 ;ROM page select port +kon equ #03 ;ON key port +lcd_crt equ #10 ;lcd control port +lcd_data equ #11 ;ldc data port + +;********************************************************************************** +;link port states + +lp_on equ #d3 ;link port off +lp_off equ #d0 ;link port on +lp_l equ #d1 ;link port left on +lp_r equ #d2 ;link port right on +lp_sw equ #03 ;toggle link port state +lp_swl equ #01 ;toggle link port state left +lp_swr equ #02 ;toggle link port state right +;lp_msk equ #d3d3 ;link port mask +lp_msk equ #d0d0 +lp_smsk equ #d1d2 ;link port stereo mask + +;********************************************************************************** +;saferam addresses + +graph_mem equ #8E29 ;768 bytes +apd_buf equ #8265 ;768 bytes +text_mem equ #80C9 ;128 bytes +text_mem2 equ #858F ;aka statram, 531 bytes +ops equ #8039 ;66 bytes + +;********************************************************************************** + +mem_end equ #f600 ;last byte of usr RAM 27463 vs 27118 (documented) + +;********************************************************************************** +;rom_call macro + +macro rom_call,addr + call addr +endm + +macro key_delay + nop + nop +endm + +;********************************************************************************** +;rom calls + +clearlcd equ #4755 ;aka _clrlcdf + +;********************************************************************************** +;shell flags + +int_state equ drumres ;apd_buf usage flag (disabled by pointing to 0 byte) diff --git a/_include/ti8xp.inc b/_include/ti8xp.inc new file mode 100644 index 0000000..2a2e318 --- /dev/null +++ b/_include/ti8xp.inc @@ -0,0 +1,77 @@ +;********************************************************************************** +;include file for TI-83Plus/TI-84Plus/Ion-compatibles +;********************************************************************************** + +progstart equ #9d95 ;all 8x+ programs start here? +;progstart equ #9d93 ;all 8x+ programs start here? + + org progstart-2 + db #bb,#6d ;and are prefixed by a token + xor a + jr nc,begin + ret + +; jr begin +; dw 0 +; db #07,#00 +; ds 4 + + +;********************************************************************************** +;ports + +link equ #00 ;link port +kbd equ #01 ;keyboard port +kon equ #04 ;ON key port??? +rom equ #07 ;ROM page select port +lcd_crt equ #10 ;lcd control port +lcd_data equ #11 ;ldc data port + +;********************************************************************************** +;link port states + +lp_on equ #03 ;link port off +lp_off equ #00 ;link port on +lp_l equ #01 ;link port left on +lp_r equ #02 ;link port right on +lp_sw equ #03 ;toggle link port state +lp_swl equ #01 ;toggle link port state left +lp_swr equ #02 ;toggle link port state right +;lp_msk equ #0303 ;link port mask +lp_msk equ #0000 +lp_smsk equ #0102 ;link port stereo mask + +;********************************************************************************** +;saferam addresses + +graph_mem equ #9340 ;aka plotscreen, 768 bytes +apd_buf equ #9872 ;768 bytes +text_mem equ #8508 ;128 bytes +text_mem2 equ #8a3a ;aka statram, 531 bytes +ops equ #8478 ;66 bytes + +;********************************************************************************** + +;ramend ;24079 (documented, ti83+) +mem_end equ #f900 ;user memory end (excl. safety margin) In theory, up to ~FB00 would be possible + +;********************************************************************************** +;rom_call macro + +macro rom_call,addr + rst #28 + dw addr +endm + +macro key_delay + push hl + pop hl +endm + +;********************************************************************************** +;rom calls + +clearlcd equ #4540 ;aka _clrlcdf + +;********************************************************************************** + diff --git a/compile.sh b/compile.sh new file mode 100755 index 0000000..23c7f3b --- /dev/null +++ b/compile.sh @@ -0,0 +1,61 @@ +#!/bin/sh + + if [ "$1" = "-82" ] + then + pasmo -d --equ MODEL=1 --alocal main.asm main.bin main.sym #> dump.lst + if [ "$?" = "0" ] + then + ./oysterpac.pl main.bin ht2.82p + rm main.bin + tilem2 -a -r "/path/to/your/rom/romfile.bin" -m ti82 ht2.82p -p "macro/ti82cr.txt" + fi + fi + if [ "$1" = "-8p" ] + then + pasmo -d --equ MODEL=4 --alocal main.asm main.bin main.sym #> dump.lst + if [ "$?" = "0" ] + then + ./oysterpac.pl main.bin ht2.82p + rm main.bin + tilem2 -a -r "/path/to/your/rom/romfile.bin" -m ti82 ht2.82p + fi + fi + if [ "$1" = "-83" ] + then + pasmo --equ MODEL=2 --alocal main.asm main.bin main.sym + if [ "$?" = "0" ] + then + cp _bin/bin8x bin8x + ./bin8x -i main.bin -o ht2.83p -nHT2 -3 -x -v + rm main.bin + rm bin8x + tilem2 -a -r "/path/to/your/rom/romfile.bin" -m ti83 ht2.83p + fi + fi + if [ "$1" = "-8x" ] + then + pasmo -d --equ MODEL=3 --alocal main.asm main.bin main.sym + if [ "$?" = "0" ] + then + cp _bin/bin8x bin8x + ./bin8x -i main.bin -o ht2.8xp -nHT2 -4 -v + rm main.bin + rm bin8x + tilem2 -a -r "/path/to/your/rom/romfile.bin" -m ti83p ht2.8xp + fi + fi +# if [ "$1" = "-73" ] +# then +# cp _bin/as73.bat as73.bat +# cp _bin/asm73.exe asm73.exe +# ./bin8x -i mark2.bin -o mark2.83p -nMARK2 -3 -v +# rm mark2.bin +# rm bin8x +# dosbox -c "cd texasi~1\PROG\mark-2" -exit "as73.bat" +# rm as73.bat +# rm asm73.exe +# mv MARK2.73P mark2.73p +# tilem2 -a -r "/path/to/your/rom/romfile.bin" -m ti73 mark2.73p +# fi + +#fi diff --git a/cpmusic.asm b/cpmusic.asm new file mode 100644 index 0000000..56b8987 --- /dev/null +++ b/cpmusic.asm @@ -0,0 +1,63 @@ +;collapsed savestate + + db #10 ;speed + ;dw #5fcd ;usr drum + +IF MODEL = TI82 + dw #5e31 +ENDIF + +IF MODEL = TI83 + dw #2bae +ENDIF + +IF MODEL = TI8X + dw #1f73 +ENDIF + db #01 ;loop point + + db #00,#02,#01,#00 ;ptn sequence + db #00,#02,#01,#01 + db #ff + + ;ptn area + db 24 ;regular note byte + db #d6 ;#d6 -> d: 0-byte, 6: for the next 6+1 = 7 rows + db 24,24,24,48 + db 43,43,43,43 + + db #d1,24,#d5 + db 24,24,36 + db 41,41,41,41 + + db 0,24,#d5 + db 24,0,24,24 + db 12,24,36,48 + + db #ff ;end of ptn area + + + ;fx ptn area + db #01+#80 ;fx ptn# (#00). bit 7 set = last fx ptn. + + db #1f,#20 + db #20,0 + db #30,0 + db #20,0 + + db #ff,#10 + db #f0,0 + db #f0,0 + db #f0,0 + + db #90,0 + db #a0,0 + db 0,0 + db #c0,0 + + db #d0,0 + db #e0,0 + db #f0,0 + db 0,0 + +;eof \ No newline at end of file diff --git a/docs/data/drumwave.png b/docs/data/drumwave.png new file mode 100644 index 0000000..f46fecf Binary files /dev/null and b/docs/data/drumwave.png differ diff --git a/docs/data/favicon.ico b/docs/data/favicon.ico new file mode 100644 index 0000000..f1ed5c4 Binary files /dev/null and b/docs/data/favicon.ico differ diff --git a/docs/data/fxptns.png b/docs/data/fxptns.png new file mode 100644 index 0000000..e71b1fc Binary files /dev/null and b/docs/data/fxptns.png differ diff --git a/docs/data/idea.jpg b/docs/data/idea.jpg new file mode 100644 index 0000000..554e095 Binary files /dev/null and b/docs/data/idea.jpg differ diff --git a/docs/data/iedummy.js b/docs/data/iedummy.js new file mode 100644 index 0000000..6a6149e --- /dev/null +++ b/docs/data/iedummy.js @@ -0,0 +1,7 @@ +//definining html5 elements for dumb browsers like IE + +document.createElement('article'); +document.createElement('nav'); +document.createElement('footer'); +document.createElement('section'); +document.createElement('time'); \ No newline at end of file diff --git a/docs/data/keymap.png b/docs/data/keymap.png new file mode 100644 index 0000000..e7fa505 Binary files /dev/null and b/docs/data/keymap.png differ diff --git a/docs/data/main.css b/docs/data/main.css new file mode 100644 index 0000000..f75da35 --- /dev/null +++ b/docs/data/main.css @@ -0,0 +1,106 @@ +div.mega { + background-color: #ffffff; + width: 100%; + font-family: Arial, Helvetica, sans-serif; + font-size: 48px; + font-weight: bold; +} + +div.header { + background-color: #ffffff; + width: 100%; + font-family: Arial, Helvetica, sans-serif; + font-size: 36px; + font-weight: bold; + page-break-before: always; +} + +div.subheader { + background-color: #ffffff; + width: 100%; + font-family: Arial, Helvetica, sans-serif; + font-size: 24px; + font-weight: bold; +} + +div.subsubheader { + background-color: #ffffff; + width: 100%; + font-family: Arial, Helvetica, sans-serif; + font-size: 20px; + font-weight: bold; +} + +div.subsubsubheader { + background-color: #ffffff; + width: 100%; + font-family: Arial, Helvetica, sans-serif; + font-size: 16px; + font-weight: bold; +} + +div.minor { + background-color: #ffffff; + width: 100%; + font-family: Arial, Helvetica, sans-serif; + font-size: 16px; + font-weight: bold; + font-style: italic; +} + +div.main { + background-color: #ffffff; + width: 80%; + font-family: Arial, Helvetica, sans-serif; + font-size: 16px; +} + +div.warn { + background-color: #ffffff; + color: #ff0000; + width: 80%; + font-family: Arial, Helvetica, sans-serif; + font-size: 16px; + font-weight: bold; +} + +div.license { + margin: 10px; + padding: 10px; + background-color: #dddddd; + + font-family: monospace; + font-size: 12px; +} + +b { + font-weight: bold; +} + +a { + color: #0000ff; + text-decoration: none; +} + +a:hover { + background-color: #0000ff; + color: #ffffff; + text-decoration: none; +} + +table { + border-collapse: collapse; +} + + +table, th, td { + border: 1px solid black; +} + +td { + padding: 4px; +} + +th { + font-weight: bold; +} \ No newline at end of file diff --git a/docs/data/noteptns.png b/docs/data/noteptns.png new file mode 100644 index 0000000..ff6e67f Binary files /dev/null and b/docs/data/noteptns.png differ diff --git a/docs/data/seq.png b/docs/data/seq.png new file mode 100644 index 0000000..1cfa656 Binary files /dev/null and b/docs/data/seq.png differ diff --git a/docs/data/tut1.png b/docs/data/tut1.png new file mode 100644 index 0000000..ed6046c Binary files /dev/null and b/docs/data/tut1.png differ diff --git a/docs/data/tut2.png b/docs/data/tut2.png new file mode 100644 index 0000000..e87ab71 Binary files /dev/null and b/docs/data/tut2.png differ diff --git a/docs/data/tut3.png b/docs/data/tut3.png new file mode 100644 index 0000000..8034d0a Binary files /dev/null and b/docs/data/tut3.png differ diff --git a/docs/data/tut4.png b/docs/data/tut4.png new file mode 100644 index 0000000..5710bf0 Binary files /dev/null and b/docs/data/tut4.png differ diff --git a/docs/data/tut5.png b/docs/data/tut5.png new file mode 100644 index 0000000..064cb3b Binary files /dev/null and b/docs/data/tut5.png differ diff --git a/docs/data/underconstr.jpg b/docs/data/underconstr.jpg new file mode 100644 index 0000000..d766f32 Binary files /dev/null and b/docs/data/underconstr.jpg differ diff --git a/docs/data/vars.png b/docs/data/vars.png new file mode 100644 index 0000000..d138b37 Binary files /dev/null and b/docs/data/vars.png differ diff --git a/docs/data/warn.jpg b/docs/data/warn.jpg new file mode 100644 index 0000000..8cdd53b Binary files /dev/null and b/docs/data/warn.jpg differ diff --git a/docs/houstontracker_2_cheatsheet.pdf b/docs/houstontracker_2_cheatsheet.pdf new file mode 100644 index 0000000..9da227e Binary files /dev/null and b/docs/houstontracker_2_cheatsheet.pdf differ diff --git a/docs/manual.html b/docs/manual.html new file mode 100644 index 0000000..bd6665a --- /dev/null +++ b/docs/manual.html @@ -0,0 +1,1405 @@ + + + + + HoustonTracker 2 Manual + + + + + + +
+ HoustonTracker 2 Manual

+
+
+ The latest version of this document can be found online at + http://irrlichtproject.de/houston/manual.html


+
+ +
+ Contents

+
+ + + +
+ 1. About
+
+
+
1.1. What is HoustonTracker 2?

+
+
+ HoustonTracker 2 is a software sequencer that enables you to create music on Texas Instruments graphing calculators. It uses the machines' communication + port to + output multi-channel 1-bit music. Its interface is inspired by popular trackers such as LSDJ, Famitracker, and Milkytracker.

+ HT2 supports several models of the Z80-based line of TI calculators. It is mainly targetted at older, obsolete models like the TI-82, but also works on newer + machines up to and including the TI-84 Plus SE. For a complete list of supported models, see section 1.3. Supported Calculators.
+

+
+ +
+ 1.2. Features

+
+
+ • 3 tone channels
+ • 1 non-interrupting drum channel
+ • up to 128 note patterns
+ • up to 64 drum/fx patterns
+ • sequence length up to 255 pattern rows
+ • 16-bit frequency precision
+ • 8-bit speed precision, can be configured per step
+ • various effects, including:
+   - L/C/R stereo hard-panning for tone and drum channels
+   - 8bit duty cycle control
+   - duty cycle sweep
+ • 2 user definable samples
+ • up to 8 savestates
+ • edit during playback
+

+
+ +
+ 1.3. Supported Calculators

+
+
+ The following table gives an overview over which TI calculator models are supported by HoustonTracker 2. If your calculator isn't listed in the table, + chances are HT2 doesn't support it.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
modelROM versionsshellHT2 buildstatus
TI-73, 73 Explorerallmallard-planned
TI-76.frallIonht2.83puntested
TI-81---not supported
TI-82< 16.0--planned
TI-8216.0-19.0CrASHht2.82psupported
TI-82 Parcus19.006CrASH196ht2p.82pbroken
TI-82 Advanced---not supported
TI-82 Stats, Stats.frallIonht2.83psupported
TI-82 PlusallDoorsCSht2.8xpsupported
TI-83 (all versions)allIonht2.83psupported
TI-83 Plus (all versions)allDoorsCSht2.8xpsupported
TI-84 Plus/Plus SEallDoorsCSht2.8xpsupported
TI-84 Plus CSE/CE---not supported
TI-85, 86---not supported
TI-89, 92, 92+, V200---not supported

+ Models marked as "not supported" have differences in architecture that would require a major rewrite of HT2. There are no plans to support these models + in the near future, especially not the 84+ Color models.
+

+
+ +
+ 1.4. License

+
+
+ HoustonTracker 2 is free, open source software. It is released under a "revised" BSD-License. This means you're basically free to use, modify, and + redistribute this software both in binary + as well as source form, as long as you don't pretend that I endorse what you're doing, or try to hold me responsible for any damage done.

+ The full license terms are as follows:

+ +
+ Copyright (c) 2015, utz^irrlicht project
+ All rights reserved.

+ + Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of IRRLICHT PROJECT nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.

+ + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +
+





+
+ + + +
+ 2. Conventions, Terms, and Definitions

+
+
+ The following section outlines some basic terms and conventions used in HoustonTracker 2, and in this documentation.


+
+ Keypress conventions

+
+
+ In this document, keypresses are denoted in bold font, surrounded by square brackets. All keypresses in HT2 are sequential, meaning you + never need to press more than one key at the same time.
+ For example, [ALPHA], [GRAPH], [ENTER] means you should first press the ALPHA key, then the GRAPH key, and finally the ENTER key. +


+
+
+ Hexadecimal notation

+
+
+ Hexadecimal numbers in this document are prefixed with 0x. So 0x20 = $20 = 20h = 32 decimal.
+ All numbers in the HoustonTracker 2 user interface itself are hexadecimal, therefore no prefix is used there.


+
+
+ Terminology

+
+
+ + + + + + + + + + + + +
bitThis humble binary digit is at the core of HT2's inner workings. It can take a value of 0 (off) or 1 (on).
byteNot related to chewing by any means, the byte is an 8-bit number. It can take any value from 0x00 (decimal 0) to 0xFF (255).
duty cycleThe relative amount of time each of the two half-periods of a square wave will consume.
hi-byteThe left two hexadecimal digits, aka most significant byte of a word.
lo-byteThe right two hexadecimal digits, aka least significant byte of a word.
nibbleA single hexadecimal digit. It consists of 4 bits, and can therefore take a value from 0x0 to 0xF (15).
patternA list of events that makes up a part of a tune. These can be notes, drum triggers, or effect commands. All patterns in HT2 are + 16 steps long.
pitchThe (perceived) frequency of a note.
shellA program that facilitates the execution of machine language programs on your TI calculator, among other things. + You'll need to install one in order to run HT2.
song sequenceA matrix containing the order of patterns. Think of it as a storyboard, or the song's masterplan.
wordA 16-bit value. Equivalent to two bytes, or four hexadecimal digits.
+





+
+
+ + + +
+ 3. Setup
+
+ +
+
3.1. Requirements

+
+
+ Hardware

+
+
+ - a TI graphing calculator (see 1.3. Supported Calculators)
+ - a suitable PC<->Calc link cable, e.g. + + TI SilverLink (recommended), + TI GraphLink, + homemade parallel + or serial cable
+ - a 2.5mm (micro-)jack adapter/cable

+ + +
You can use a cheap calc-to-calc link cable to make your own 2.5mm adapter.

+ + +
The plastic base of many adapters is too thick to fit into + TI's extra narrow socket. If that's the case, you need to carefully scrape off some plastic from the base of the jack until it fits.


+
+ Software

+
+ In addition to the HT2 executable, you will also need to obtain:

+ - TI linking software for exchanging data between your PC and your calc (recommended: TiLP)
+ - a so-called "shell" for your calculator. The following table lists the recommended shells for each model. Other shells may work, but haven't been tested. +

+ + + + + + + + + + + + + + + + + +
+ model + + shell +
+ TI-82 + + CrASH 1.6 +
+ TI-83, TI-82Stats + + Ion 1.6U +
+ TI-83 Plus, TI-84 Plus + + Doors CS 7 +
+
+ + +
HT2 is not compatible with MirageOS.



+
+ +
+ 3.2. Installation

+
+
+ + +
After installing HoustonTracker 2, your calculator will not be able to perform most of its regular tasks until HT2 is + removed. + Do not install HT2 if you need to use your calculator for regular work, such as in school or university.


+
+
+ The following instructions assume that you have TiLP installed on your computer. If you are using another linking program, then you probably + know what to do...


+
+
+ Installing on TI82

+
+
+ Step 1: Reset your calculator by pressing [2nd], [+], [3].
+ Step 2: Switch off your calculator, and connect it to your computer with a link cable.
+ Step 3: Switch the calculator back on.
+ Step 4: On your computer, open TiLP. Make sure your calculator and link cable settings are correct - if not, press Ctrl+D to reconfigure.
+ Step 5: Put your calculator into transmission mode by pressing [2nd], [X,T,Θ], [▸], [ENTER].
+ Step 6: In Tilp, go to "File"->"Restore", and select CRASH.82B from the CrASH package. Doing so will prompt for confirmation on both TiLP and your calc.
+ Step 7: Assuming all went good, you can now put your calc in transmission mode again, and send ("File"->"Send Files") ht2.82p.

+
+
+ + +
If you intend to use a SilverLink cable in conjunction with a TI-82, do not install the official TI connectivity + software on your computer. If you currently have + TI Connect installed, or had it installed in the past, make sure you fully remove all of its components, especially the USB driver that came with it.

+
+
+ Installing on TI83/TI82Stats

+
+
+ Step 1: Reset your calculator by pressing [2nd], [+], [5].
+ Step 2: Switch off your calculator, and connect it to your computer with a link cable.
+ Step 3: Switch the calculator back on.
+ Step 4: On your computer, open TiLP. Make sure your calculator and link cable settings are correct - if not, press Ctrl+D to reconfigure.
+ Step 5: Put your calculator into transmission mode by pressing [2nd], [X,T,Θ,n], [▸], [ENTER].
+ Step 6: In Tilp, go to "File"->"Send Files", and select ION.83G from the Ion package.
+ Step 7: After Ion has been received by the calculator, quit the link menu with [2nd], [MODE]. Now press [PRGM], select "ION", and press [ENTER].
+ Step 8: Press [2nd], [+], [2], [7]. Select ION and press [ENTER] to delete it. Likewise, delete IONZ.
+ Step 9: Assuming all went good, you can now put your calc in transmission mode again, and send ("File"->"Send Files") ht2.83p.


+
+
+ Installing on TI83 Plus/TI84 Plus

+
+
+ Step 1: Reset your calculator by pressing [2nd], [+], [7], [▸], [▸], [ENTER].
+ Step 2: Switch off your calculator, and connect it to your computer with a link cable. This will switch your calc back on.
+ Step 3: On your computer, open TiLP. Make sure your calculator and link cable settings are correct - if not, press Ctrl+D to reconfigure.
+ Step 4: In Tilp, go to "File"->"Send Files", and select DoorsCS7.8xk from the DoorsCS package.
+ Step 5: Assuming all went good, you can now send ("File"->"Send Files") ht2.8xp.


+
+
+ + + +
+ For faster access, you can use TiLP in GUI-less mode. To do so, open a command prompt (cmd.exe on Win or any shell on *nix), + and enter the following command:
+
+ tilp [calc-model] [cable-model] [filename] +
+ So, to send HT2 to your TI83 Plus via a SilverLink cable, you would type +
+ tilp ti83+ SilverLink ht2.8xp +
+



+
+ +
+ 3.3. Running HT2

+
+
+ Once you've successfully installed HT2, running it is very simple.

+ Step 1: Press [PRGM] (TI82/83), resp. [APPS] (TI83 Plus/84 Plus).
+ Step 2: Select "CRASH" (TI82), "A" (TI83), resp. "DoorsCS" (Plus models), and press [ENTER].
+ Step 3: Make sure HoustonTracker 2 is highlighted, and press [ENTER] again. Unless an error occured, HT2 is now running.
+ Step 4: Now plug in your audio cable or headphones.

+ + After exiting HT2 with keys [ALPHA],[ON], you will be returned to the Shell. Press [MODE] (CrASH, Ion) resp. [CLEAR] (DoorsCS) to exit + it.

+ + +
On TI83/8x Plus, booting and shutting down HT2 will take up to 10 seconds.





+
+ + + +
+ 4. Using HT2

+
+ +
+ 4.1. Quickstart Tutorial

+
+
+ The following section will explain how to get started with HoustonTracker 2 in 10 easy steps. + If you can't be bothered to read the whole manual, and want to get started with HT2 in 5 minutes, then this section is for you.


+ Step 1: Start Houston Tracker, and plug in your audio/headphone cable. Check the previous sections if you can't figure out + how to do that.

+ + +
Always plug in headphones after you've started HT2.


+ Step 2: Enter some patterns into the song sequence. To do so, press the following keys: [0],[0],[0],[1],[0],[2],[0],[0]. + Your main screen should now look like this:




+ Step 3: Move the cursor up to the first position in the sequence again. Now press [2nd]. This will bring up the pattern screen.

+


+ Step 4: Let's activate RowPlay mode, so we can hear what we're doing. Press [ALPHA],[MODE],[ALPHA].


+ Step 5: Ok, let's put some notes into this pattern thing. Press [PRGM],[PRGM].


+ Step 6: Wow, that's a pretty low note. Let's change the octave by pressing [GRAPH],[2]. Now we can enter some more notes, for example + by pressing [PRGM],[PRMG],[SIN],[SIN],[TAN],[TAN].




+ Step 7: Press [ENTER] to hear what we've got so far.


+ Step 8: Hmmm, sounds pretty boring, right? So let's spice things up with some drums. Press [2nd] to go back to the main screen. + Now move the cursor all the way to the right, and press [2nd] again. This will bring up the FX pattern screen.

+


+ Step 9: Press [1],[▾],[2],[2],[1],[▾],[2],[2],[1],[▾],[2],[2],[▾],[2],[▾],[2].

+


+ Step 10: Congratulations, you've just composed your first "song" in HoustonTracker 2!



+
+ +
+
4.2. Keys

+
+
+ Houstontracker Keymap

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
keystandard functionALPHA mode functionDescription
 
[ON]-QUITExit HT2. The current tune will be preserved in memory. You can only exit when music isn't playing. On TI83/8x Plus, this will take a few moments.
 
[Y=]LOADSAVELoad a song. Will prompt for a save slot number (0..7). Needs to be CONFirmed.
+ In ALPHA mode, save the current song. Will prompt for a save slot number (0..7). Needs to be CONFirmed.
[WINDOW]ZAP SONGDEL SLOTClears the current tune. Needs to be CONFirmed.
+ In ALPHA mode, prompt for a save slot number (0..7) and deletes it. Needs to be CONFirmed.
 
[.]CONFIRM-Confirm action. (Cancel action with key [0].)
 
[2nd]TOGGLE SEQ/PTN-Toggle between sequence and pattern view. When used on sequence view, it will display the pattern selected by the cursor.
[ALPHA]ALPHA MODE ONALPHA MODE OFFToggle ALPHA mode on and off.
TIP: When music is playing, you can hold down this key to pause the playback.
[MODE]TOGGLE AUTOINCTOGGLE ROWPLAYToggle automatic cursor increment on/off (on by default).
+ In ALPHA mode, toggle playing notes while editing (off by default). Beware that RowPlay may ignore effect settings under certain circumstances.
 
[▴]MOVE UPJUMP TO STARTMove cursor up. In ALPHA mode, jump to row 00 of the sequence.
[▾]MOVE DOWNJUMP TO ENDMove cursor down. In ALPHA mode, jump to the last rows in the sequence.
[◂]MOVE LEFTPGUP/PREV PTNMove cursor left. In ALPHA mode, move one page (10 lines) up in sequence.
+ On pattern screens, cycle through patterns in ALPHA mode.
[▸]MOVE RIGHTPGDOWN/NEXT PTNMove cursor right. In ALPHA mode, move one page (10 lines) down in sequence.
+ On pattern screens, cycle through patterns in ALPHA mode.
 
[ENTER]PLAY/STOP-Start playing from row 00, or stop playback if player is running.
[(-)]PLAY CURR/ PAUSE-Start playing from the current position in sequence, or hold down to pause playback while player is running.
 
[0]0/DEL NOTE/CANCELREMOVE PTNDepending on context, either input 0 at cursor, delete a note, or cancel action.
+ On the Sequence screen and with ALPHA mode active, remove the currently selected pattern from the sequence.
[1]..[9]1..9-Input 1..9 at cursor.
[MATH]AA#Input hex digit A or note A at cursor, depending on the context. While setting notes and being in ALPHA mode, input an A#.
[MATRIX]/[APPS]B-Input hex digit B or note B at cursor, depending on the context.
[PRGM]CC#Input hex digit C or note C at cursor, depending on the context. While setting notes and being in ALPHA mode, input a C#.
[x⁻¹]DD#Input hex digit D or note D at cursor, depending on the context. While setting notes and being in ALPHA mode, input a D#.
[SIN]E-Input hex digit E or note E at cursor, depending on the context.
[COS]FF#Input hex digit F or note F at cursor, depending on the context. While setting notes and being in ALPHA mode, input an F#.
[TAN]GG#Input note G at cursor. While setting notes and being in ALPHA mode, input a G#.
This key does nothing in sequence/fx ptn view.
 
[,]MUTE CH1UNMUTE ALLMute/unmute channel 1. In ALPHA mode, unmute all channels.
[(]MUTE CH2MUTE DRUMSMute/unmute channel 2. In ALPHA mode, mute/unmute drum channel.
[)]MUTE CH3MUTE ALLMute/unmute channel 3. In ALPHA mode, mute all channels.
 
[TRACE]SET SPEEDSET USR DRUMSet the global song speed.
In ALPHA mode, set the user drum pointer. Any value between 0x0000 and 0xFFFF is permitted. However, + it is recommended to stick with values in the range of 0x0000 - 0x7FFF, as higher values may produce unpredictable results.
[GRAPH]SET OCTAVE-Set the current octave. Only works on note pattern screens. Valid values are 0..6.
 
[X,T,Θ]TRANSPOSE UPTRANSPOSE DOWNTranspose current pattern up by one half-tone. In ALPHA mode, transpose current pattern down by one half-tone.
+ Out-of-range notes will be replaced with rests.
 
[x²]QUICK SET LPSET LPSet the loop point to the current row in sequence. Only works on sequence screen.
In ALPHA mode, enter a new LP value. Changes will not + take effect until the next player restart.
 
[LN]QUICK SET BSSET BSSet Block Start to the current row in sequence. Only works on sequence screen.
In ALPHA mode, enter a new BS value.
[STO►]QUICK SET BESET BESet Block End to the current row in sequence. Only works on sequence screen.
In ALPHA mode, enter a new BE value.
 
[÷]DEL ROWDEL BLOCKDelete the current row.
In ALPHA mode, delete the selected block.
[×]INS BLOCKPASTE BLOCKInsert a copy of the selected block at the cursor.
In ALPHA mode, paste selected block over the current and following rows.
+ The target row must be outside of the selected block.
[-]COPY ROW-Insert a copy of the current row at the cursor.
[+]PUT NEXT FREECLONE CURRPut the next unused free pattern in sequence at the current position.
In ALPHA mode, clone the current pattern and insert the + clone at the current cursor position.
+



+
+ +
+ 4.3. Composing Music

+
+ +
+ 4.3.1. Modes, Indicators, and Global Variables

+
+
+   

+ Modes and Indicators

+
+
+ There are a number of different indicators, which will tell you about various modes and editing settings that are currently applied.

+ The Alpha mode indicator comes in the shape of a capital letter A, which is displayed below the diagonal left edge of the + HT2 logo. + When the A is visible, then Alpha mode is active. The Alpha mode is HT2's version of CAPS LOCK. Many keys in HT2 have a primary and secondary function. + In Alpha mode, the secondary functions will be triggered. You can toggle Alpha mode on and off by pressing - you guessed it - [ALPHA].

+ The playback indicators are located directly below the HT2 logo. The first position tells you if the music player is + currently stopped or running. While stopped, it will display a ■, when running, it will display the capital letter P. Next to this position, you + will find four positions which normally read "123D" (for channel 1, 2, 3, and drums respectively). These positions indicate which channels are currently + muted. Muted channels will display a "-" instead of their channel number/letter.

+ The AutoInc/RowPlay indicators tell you whether the auto-incrementing and RowPlay functions are currently activated. They + are located in the lower third of the right screen side, just below the the global variables. The AutoInc indicator displays "A1" when + auto-incrementing is + active, and A0 when inactive. Auto-incrementing means that after you enter a value or note in HT2, the cursor will automatically advance to the next position. + You can toggle AutoInc with key [MODE]. The RowPlay indicator tells you whether RowPlay mode is currently active. If so, it will display the + capital letter P. When entering a note, HT2 will + automatically play the current pattern position (including all channels that are not muted). You can toggle RowPlay by activating [ALPHA] mode, and + then pressing key [MODE].

+ + +
RowPlay mode can't reliably detect all effect settings that apply to the current position, so depending on the + circumstances, + it may not reflect how the position will actually sound when the whole song is played back.

+ Below the AutoInc/RowPlay indicators, there is the general purpose message area. Here, various important messages will be + displayed, such as occuring errors, or requests for the user to confirm an action. Confirming is done with key [.], cancelling is done with key + [0]. +


+
+
+ Global Variables

+
+
+ The loop point defines what row in the sequence the player will loop back to after it has reached the end of the song. + Pressing [x²] will set the loop point to the row currently highlighted by the cursor. To set it to another row, first enter [ALPHA] mode, + then press [x²] and enter a 2-digit hex number.

+ + The global song speed can be changed by pressing [TRACE], followed by a 2-digit hex number. Generally, the higher + the number, the lower the speed. However, 0x00 is an exception. It is the slowest possible setting, equivalent to a speed of 0x100.

+ + To set the user drum pointer, go into [ALPHA] mode, then press [TRACE], followed by a 4-digit hex number. + See the section on drums for + details about the user drum pointer.

+ + +
Changes to the global variables are not effective until you restart the player.



+
+ +
+ 4.3.2. Editing the Song Sequence

+
+
+    +

+
+
+ The sequence screen is where you build the general structure of your song. It consists of four editable columns, each containing a list of patterns. + Each column represents a different channel. To toggle between the main (sequence) screen and the pattern screens, select a pattern in the sequence + with the cursor, then press [2nd].

+ The first 3 columns represent the 3 tone channels, ie. they contain note patterns. The last channel represents the drum channel and + effects settings, ie. it contains fx patterns. + The tone channels differ somewhat in sound and features. Channel 1 features the A0x effect, which adds noise and/or glitchy + sounds to the regular tone. Channel 2 is somewhat louder than the other channels. It features a variable duty cycle and the duty cycle sweep effect. + Channel 3 features hi-speed pitch slides. It also sports a variably duty cycle.

+

+
+
+ Moving around on the sequence screen

+
+
+ Keys [▴], [▾], [◂], and [▸] move the cursor around on the sequence screen.

+ Pressing [◂] resp. [▸] in [ALPHA] mode will move the cursor up/down by 10 rows.

+ Pressing [▴] in [ALPHA] mode will move the cursor to the start of the sequence. Likewise, pressing [▾] in [ALPHA] mode will move + the cursor to the end of the sequence.
+


+
+
+ Editing the sequence

+
+
+ Use keys [0]..[9] and A..F ([MATH], [MATRX] resp. [APPS], [PRGM], [x⁻¹], + [SIN], and [COS]) to enter pattern numbers. You can have a maximum of 128 note patterns, and 64 fx patterns, so the + highest pattern numbers are 0x7F and 0x3F respectively. Note patterns are shared across all 3 tone channels, so you can use any note pattern on any channel. + If you try to enter an invalid pattern number, HT2 will automatically replace it with an arbitrary valid one.

+ + +
Note patterns and fx patterns use a different numbering, e.g. note pattern 01 is + different from fx pattern 01.

+ To automatically put the first unused pattern at the current sequence position, press [+]. To clone the pattern at the current position (copy it's + contents to a new, unused pattern), press [+] in [ALPHA] mode.

+ To delete the pattern number at the current position, press [0] in [ALPHA] mode.

+ You can press [-] to copy the current row. This will insert the copy at the current position.

+ Press [÷] to delete the current row.



+
+
+ Block Operations

+
+
+ HT2 uses two block markers, block start (BS) and block end (BE) to select a section of sequence data for copying, pasting, and cutting. + Block operations work only on the whole sequence, not on individual channels.

+ To set the block start to the current row in the sequence, press [LN]. Likewise, to set the block end to the current row, press [STO►]. + Pressing these keys in [ALPHA] mode will allow you to set the BS/BE positions manually.

+ To copy the marked block and insert it at the current cursor position, press [×]. Pressing [×] in [ALPHA] mode will + paste the block over the following sequence rows. Note that you cannot insert/paste a block into itself, so the target must always be outside the selected + block.

+ Press [÷] in [ALPHA] mode to delete the selected block and move the following sequence data up.

+

+
+ +
+ 4.3.3. Editing Note Patterns

+
+
+    +

+
+
+ All note patterns have a fixed length of 16 steps, which are organized in two columns à 8 steps.

+ Notes can be entered with keys [MATH] (A), [MATRX] resp. [APPS] (B), [PRGM] (C), [x⁻¹] (D), [SIN] (E), + [COS] (F), and [TAN] (G). Sharp notes (black keys) can be reached in [ALPHA] mode.

+ In order to hear notes while you're entering them, you can toggle RowPlay by pressing [MODE] in [ALPHA] mode. A "P" will be displayed + next to the AutoInc indicator to let you know that RowPlay is active. Note that RowPlay is somewhat + limited. Among other things, it may ignore current effect settings. Also, it will fail if the pattern you're editing is not on the current step in the song + sequence. +

+ To change the current octave, press [GRAPH], then enter a number between 0 and 6. You can also edit octaves manually in the pattern.

+ + +
To cycle through note patterns, you can use keys [◂] and [▸] in [ALPHA] mode. +

+ +
In order to use a different pattern length, you can utilize the B00 effect command. +



+
+ +
+ 4.3.4. Editing Drum/Effects Patterns

+
+
+    +

+
+
+ Like with note patterns, fx patterns are organized in two columns à 8 steps. Each step consists of four hex digits. + The first digit sets the drum sound to be used on that step. A value of 0 means no drum. Refer to the following section + to learn more about drums in HT2.

+ The second digit sets the effect command. A value of 0 means no effect. Finally, the last two digits set the effect parameters. + Refer to section 4.3.4.2 to learn all about effects. +


+
+ +
+ 4.3.4.1. Drums

+
+
+ There are 15 different drums to chose from (0x1..0xF). Some of the drums use the TI-OS as sample data, so their sound may vary across + different calculator models.

+ Drums can be played in different modes, which affects the way they sound. Use command Cxx to change the drum mode, with xx = 0x00..0x4f. There are 80 + different drum modes, though not all of them are particularly useful.

+ Setting a non-zero value for the lower nibble of the parameter causes the drum data to be manipulated in various ways. Refer to + Appendix C for details about this functionality.

+ The upper nibble of the parameter + defines the behaviour of the drum data pointer. The effects are as follows:

+ + + + + + + +
modecommandeffect
0C00Increment pointer, ie. use the "standard" drum set.
1C1xDecrement pointer, ie. use the "alternative" drum set. Generally speaking, these drums are less useful than the standard set. + Also, some drums will produce unpredictable results, namely drum 0, 1, C, and D.
2C2xIncrement and loop pointer. Even less useful than mode 1, and suffers from the same problems. Also, this mode causes a slight + global pitch shift.
3C3xDecrement and loop pointer. Like mode 2, with different sounds.
4C4xDon't move pointer. Instead of drums, in this mode triggering a drum will play a fixed, most likely out-of-tune frequency. + This mode causes a slight + global pitch shift.

+ Drum 0xE and 0xF are special cases.

+ 0xF is the user drum pointer, which can be configured individually. To change it, go into [ALPHA] mode, then press [TRACE].
The user drum + pointer + can be set to any value between $0000 and $FFFF. However, if you want to play it safe you should keep the pointer in range 0x0000 - 0x7FFF. This is because + the user drum + is actually a pointer to ROM/RAM. Pointing the user drum to RAM (0x8000 and up) will give unpredictable results, as the RAM contents change frequently. +

+ 0xE is the user defined sample. This feature is a bit quirky in use. In order to create a custom sample, go to FX pattern 0x20. Now, instead of entering + the usual drum triggers, fx commands, and fx parameters, you enter your sample data. You can use more than one pattern, so after you've filled up FX pattern + 0x20, go to 0x21.

+ The data is in 1-bit PWM format, meaning each byte denotes a phase length. + Think of it as the amount of time taken until the beeper output will toggle again. The values are inverse, ie. a lower value denotes a longer phase. + Yes, it's a bit confusing... As an example, this is what drum sample 1 (the kick drum) looks like: +
+ 0x80, 0x80, 0x70, 0x70, 0x60, 0x60, 0x50, 0x50, 0x40, 0x40, 0x40, 0x30, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, + 0x0 +
+ This will give you a waveform looking like this:

+ image of drum waveform

+ +
The last byte of the sample must be 0. +

+ +
You can even define a second drum sample, which you can then trigger in drum mode C1x/C3x. This sample also starts at + FX pattern 0x20, but needs to be written backwards, + so the second byte of the sample is on the last position (FX parameter of the last row) of FX pattern 0x1F, third byte is just before that (drum/FX command + of the last row), + and so forth. +

+ +
+

+
+ +
+ 4.3.4.2. Effects Reference

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
commandeffectdescription
1xySET PANSet panning for all channels. To determine how the panning will be set, you need to look at the individual bits of the effect parameter, starting + at the rightmost one (aka bit 0).

+    bit 0 set: pan channel 1 right (add 0x01 to parameter)
+    bit 1 set: pan channel 1 left (add 0x02 to parameter)
+    bit 0,1 reset: pan channel 1 center (don't add anything to parameter)
+    bit 2 set: pan channel 2 right (add 0x04 to parameter)
+    bit 3 set: pan channel 2 left (add 0x08 to parameter)
+    bit 2,3 reset: pan channel 2 center (don't add anything to parameter)
+    bit 4 set: pan channel 3 right (add 0x10 to parameter)
+    bit 5 set: pan channel 3 left (add 0x20 to parameter)
+    bit 4,5 reset: pan channel 3 center (don't add anything to parameter)
+    bit 6 set: pan drums right (add 0x40 to parameter)
+    bit 7 set: pan drums left (add 0x80 to parameter)
+    bit 6,7 reset: pan drums center (don't add anything to parameter)

+ Example: + + + + + +
commandbitmaskcalculationeffect
100000000000x00 + 0x00 + 0x00 + 0x00 = 0x00pan all channels to center
155010101010x01 + 0x04 + 0x10 + 0x40 = 0x55pan all channels right
112000100100x02 + 0x00 + 0x10 + 0x00 = 0x12pan ch1 left, ch2 center, ch3 right, drums center
+
2xxPITCH SLIDE UP CH3Cause a (rather fast) upward pitch slide on channel 3. While this effect is active, rests will be ignored on channel 3.
+ xx defines the speed of the slide. It can be any value, but beware that the pitch counter will eventually wrap.
0x00 switches off the effect.
+
3xxPITCH SLIDE DOWN CH3Cause a very fast downward pitch slide on channel 3. While this effect is active, rests will be ignored on channel 3.
+ xx defines the speed. It can be any value, but beware that the pitch counter will eventually wrap, after which the pitch will start to slide upwards. +

+ +
This effect is switched off with command 200. + Entering 300 causes a glitchy effect instead (like 3FF, but even faster). +
+
40xDUTY CYCLE SWEEP CH2Do a SID-style duty cycle sweep on channel 2. This will override any duty cycle settings on that channel.
+ 401 activates the effect, 400 deactivates it and resets the duty cycle to 50:50.
+
5xxDUTY CYCLE CH2Set the duty cycle for channel 2.
+ xx can be any value, but 0x00 will cause glitches. A value of 0x80 produces the default 50:50 wave.
+
6xxDUTY CYCLE CH3Set the duty cycle for channel 3.
+ xx can be any value, but 0x00 will cause glitches. A value of 0x80 produces the default 50:50 wave.
+
A0xADD SFX CH1Add a sound effect to channel 1.
+ A00 deactivates the effect.
+ A01 adds noise or glitchy sounds to channel 1. The actual outcome depends on the current pitch of ch1. To some extend, it's also influenced by the + currently active drum sound.
+ A02 adds slight random inaccuracies to the pitch of channel 1. It has little effect by itself, but can be used to produce a phasing effect in + conjunction with other channels + set to the same note as ch1. The effect does not work equally well on all pitches, namely it won't do anything on C notes.
B00BREAK PTNBreak pattern and jump to the next one. This command doesn't take any parameters. Also, it is ignored on the first line of a pattern.
CxxDRUM MODESet the drum mode, where x is 0x00..0x4F. Refer to the drums section for details.
+
D0xVOLUME CH1/DDouble the volume for channel 1, at the expense of switching off the drums.
+ D01 activates the effect, D00 switches it off.
E0xRESET FXReset previous FX commands to default settings. This effect causes a slightly longer than normal delay when triggered.
+ E00 - reset all effects.
+ E01 - reset all effects except speed.
+ E02 - reset all effects except speed and duty cycles.
+ E03 - reset all effects except speed, duty cycles, and panning settings.
FxySET SPEEDSet the current speed. xy can be any hexadecimal number between 0x01 and 0xFF. The higher the value, the slower the speed. This command + overrides the global speed setting.
+ TIP: When entering this effect while the player is running, make sure to enter the parameter first, and then the F command.
+


+
+ +
+ 4.4. Loading, Saving, and Backing Up

+
+
+ Saving

+
+
+ To save your current work in progress, activate [ALPHA] mode, then press [Y=]. The letters "SA" will appear in the message area. + Now, enter the number of the save slot you want to load (0..7), and confirm by pressing [.]. (If you got here by accident, press [0] + to cancel.)

+ If the save was successful, error code E0 will be displayed in the message area. If the save was unsuccessful due to insufficient memory, error code + E2 will be displayed instead. Note that you may run out of memory rather quickly. You will always be able to maintain at least two save slots, however. +


+
+
+ Loading

+
+
+ To load a previously saved tune, simply press [Y=]. The letters "LD" will appear in the message area.
+ Now, enter the number of the save slot you want to load (0..7), and confirm by pressing [.]. (If you got here by accident, press [0] + to cancel.)
+ The tune in question will be loaded, or error code E5 will be printed if the selected save slot was empty. +


+
+
+ Deleting a save slot

+
+
+ In case you run out of memory, or want to get rid of one of your save slots for other reasons, you can specify a save slot to be deleted.
+ In order to do so, activate [ALPHA] mode, then press [WINDOW]. The letters "DS" will appear in the message area.
Now, enter the number + of the save slot you want to delete (0..7), and confirm by pressing [.]. (If you got here by accident, press [0] to cancel.)
+ And that's all you need to know about deleting save slots! +


+
+
+ Backups

+
+
+ Creating a backup of your HT2 songs is trivial: Simply send the HT2 PRGM file to your computer or another calc of the same model. + The program file contains all the save slots as well as the currently loaded song.

+  In the future, there will be a PC utility for manipuling backup files. +



+
+ +
+ 4.5. Error Codes

+
+
+ If a major error happens, HT2 will attempt to detect it, and print an error code in the message area. An special error message will also be displayed if + saving a backup of the current song was successful.

+ The following table lists all possible error codes:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
codenamedescription
E0SAVE OKSaving backup was successful, no error occured.
E1INVALID BLOCKBlock End is set before Block Start, or the row where the block should be inserted/pasted to is within the selected block.
E2INSUFFICIENT MEMORYThere is not enough RAM to perform the desired action (usually saving).
E3INVALID PTNAn invalid pattern number was set in the song sequence.
E4LP INVALIDInvalid loop point. Row to loop to is empty.
E5FILE I/O ERRLoading song failed. Save slot is empty or corrupt.
E6SAVESTATE ERRWrong savestate version, or savestate corrupt.
E7NO FREE PTNCould not find a free pattern.
E8BLOCK TOO LARGEThe selected block is too large to be inserted.
+
+ Small errors (like trying to set an inexistent note or an invalid pattern number) will be simply ignored by HT2.
+




+
+ + +
+ 5. Thanks, Credits, and Greetings

+
+
+ Thanks to...

+ ... TylerBarnes, Tronimal, garvalf, and Flashbob for beta testing
+ ... extra thanks to garvalf for preparing the HT2 cheatsheet
+ ... Shiru, introspec, and Alone Coder for their expertise and advice
+ ... Brandon Wilson, Lionel Debroux, and everybody who has been hacking/documenting TI calcs

+ The TI-82 image that was used as the basis of the keymap was authored by Martin Olsson, and is released under + a GDFL/Creative Commons BY-SA license. +




+
+ + +
+ Appendix A: Building from Source

+
+
+ The latest version of the HT2 source code can always be found at + github.com/utz82/HoustonTracker2

+ HoustonTracker 2 is developed under Linux. If you're running Linux or another *nix derivate, building HT2 is a matter of simply running the build script, + provided you have a few basic tools installed. If you're developing on Windows or another non-Posix compliant system, you'll need to provide your own build + script or build from hand.

+
+ Building Requirements

+
+ • The Pasmo assembler must be installed and present in your search path (unless you want to adapt the + sources for another assembler).
+ • When targetting the TI-82, you will also need Perl installed on your system. + If on *nix, you most likely have it already installed.
+ • Optionally, you may want to install an TI calculator emulator. For *nix systems, using the development version of + tilem2 is recommended.
+
+
+ Building with the Build Script (*nix only)

+
+ It's as simple as opening a terminal, navigating to the folder containing HT2, and typing
+
+ ./compile.sh -[model] +
+ where [model] is one of

+ + + + + +
82build for TI-82
8pbuild for TI-82 Parcus
83build for TI-83, TI-82 Stats
8xbuild for TI-83 Plus, TI-84 Plus etc.
+
+ Optionally, you can rebuild the note table before running the build script. In order to do so, run the tablegen.sh + shell script. This will allow you to change HT2's base tuning. +

+ In order to have the build script automatically run your builds in tilem2, uncomment the lines in compile.sh that look like this: +
+ tilem2 -a -r "/path/to/your/romfiles/xyz.rom" -m [model] [buildfile] +
+

+
+ Building by Hand

+
+ The following steps are required to build HT2 by hand:

+ 1. Assemble the sources with the following command: +
+ pasmo --equ MODEL=[model] --alocal main.asm main.bin +
+ + where [model] can be either 1 (TI-82 build), 2 (TI-83 build), 3 (Plus models build), or 4 (TI-82 Parcus build). +

+ 2. Pack the resulting main.bin into a TI executable (82p, 83p, 8xp) using a packer of your choice (bin8x, oysterpac.pl, etc...).
+




+
+ + +
+ Appendix B: Data Format Specification

+
+
+ Work Area Data Format

+
+
+ The work area is where HT2 stores the currently loaded song. It begins at label "musicData", and is 5125 bytes in size. The actual address in memory + depends on the version of HT2.

+ + + + + + + + + +
offsetlengthdescription
+0byteglobal speed
+1worduser drum pointer
+3byteloop point
+41 KBpattern sequence list. 1 byte per pattern. Order is ch1, ch2, ch3, fx. Empty positions contain 0xff.
+1028byteone 0xFF byte to mark the end of the sequence list.
+10292 KBnote patterns. Each note pattern has an uncompressed length of 16 bytes. Empty positions contain 0x00.
+30772 KBFX patterns. Each fx pattern has an uncompressed length of 32 bytes. Empty positions contain 0x00.
+

+
+
+ Compressed Savestate Format

+
+
+ HT2 uses a very simple compression scheme to store song data backups. They are set up as follows:

+ + + + + + + + + + +
offsetlengthdescription
+0byteglobal speed
+1worduser drum pointer
+3byteloop point
+4?pattern sequence list. 1 byte per pattern. Order is ch1, ch2, ch3, fx.
?byteone 0xFF byte to mark the end of the sequence list.
??note patterns.
+ if byte at offset >= 0xE0, then the following [byte - 0xDF] patterns are empty.
+ else, if byte at offset >= 0xD0, then the following [byte - 0xCF] rows are empty.
+ else, if byte at offset < 0xD0, it's a regular note value. +
?byteone 0xFF byte to mark the end of the note pattern area.
??FX patterns.
+ FX patterns are preceded by their pattern number. A pattern number of 0xFF signals that the savestate contains no FX patterns.
+ If bit 7 of the pattern number is set, it's the last pattern to be loaded. Setting bit 7 is optional if the last saved FX pattern is 0x3F.
+


+ Start and end addresses of backup savestates are stored in the savestate lookup table. +




+
+ + +
+ Appendix C: Synthesis Techniques

+
+
+ The following section describes how the multi-channel synthesis is achieved in HT2, and how the effects are produced.


+
+
+ General Notes

+
+
+ Sound mixing in HT2 is achieved through a 1-bit synthesis technique called Pulse Interleaving.

+ Typically, a 1-bit DAC can only output one single square wave frequency. What Pulse Interleaving does is interlace the multiple software channels + at a rapid rate. Due to their own hardware latency, common output devices such as speakers or headphones cannot fully adjust their speaker cones at this rate. + Therefore the cones will be left in a floating state between full extension and full contraction. This is how the + different volume levels needed to mix HT2's four software channels are achieved.

+ The average time taken to interlace one sample of all 4 channels is (1/16300)s, meaning channel states are swapped + at a rate of about 65200 Hz. The exact timings depend on various factors such as actual tone frequencies, effect and drum settings, hardware model, + and battery state.

+ Internally, three different methods are applied to generate the software channel outputs. Tone channel 2 and 3 share the same method, while channel 1 and + the drum channel use their own respective techniques.


+
+
+ Tone Channel 1

+
+
+ Once per interlacing cylce, a 16-bit constant (the "frequency base value") is added to a 16-bit counter. When the addition produces an overflow + (carry, result >0xFFFF), the channels' output stated will be toggled. This means of course that channel 1 has to keep a record of its own output state. +

+ The A01 effect (noise/glitch) is achieved by constantly rotating the hi-byte of the add counter. This may or may not generate enough pseudo-randomness to + produce a noise-like effect, depending on the frequency base value. Likewise, the A02 effect will rotate the lo-byte of the add counter.


+
+
+ Channels 2 and 3

+
+
+ Tone channels 2 and 3 do not keep a record of their own output state. Instead, they recalculate the output state on every interlacing cycle. In order to + do this, the hi-byte of the add counter is compared against a threshold value. If the threshold constant is greater than the hi-byte of the add counter, + the output state will be high (1), otherwise it will be low (0).

+ The threshold value determines the duty cycle ratio. When the threshold is 0x80, the output state will be high 50% of the time, and low for the + other 50%. When the threshold is, say, 0x40, the ratio will be 25%:75%.

+ The D01 effect (duty cycle sweep) is achieved by incrementing the threshold value once every interlacing cycle. As it is an 8-bit value, it will wrap to + 0 once it reaches 0xFF.

+ The pitch slides are achieved by adding a constant to the frequency base value once per interlacing cycle.


+
+
+ Drum Channel

+
+
+ Drums are generated from values in either ROM or RAM. The values read will be interpreted as 8-bit counters, which are decremented once per interlacing cycle. + When the counter reaches 0, the output state of the drum channel is toggled, and the next value is read from ROM/RAM. When a 0-byte is read, + the output stops.

+ Drums 0x1, 0xC, and 0xD are hard-coded in RAM. The "user drum sample" (drum 0xE) is effectively a pointer to FX pattern 0x20. The "user drum pointer" + (drum 0xF) is a simple user-definable pointer which can point to either RAM or ROM. All other drums point to ROM, which explains why they sound different + depending on what calculator model is used.

+ The "drum mode" effect (Cxx) will do two things. The upper nibble of the effect parameter determines the direction of the ROM/RAM pointer used to retrieve the + counter values. If the upper nibble is 0, the pointer will move forward. If 1, it will move backward. If 2 or 3, only the lo-byte of the pointer will be + in/decremented, which means the pointer stays on the same 256-byte memory page. If 4, the pointer will not be moved at all.

+ The lower nibble of the effect parameter will determine how the values are modified after they are read from memory. The manipulations are as follows:

+ + + + + + + + + + + + + + + + + + +
 value effect
0x0no manipulation
0x1transform into binary coded decimal
0x2multiply by 2
0x3divide by 2
0x41's complement
0x5use lo-byte of pointer as value
0x6add lo-byte of pointer
0x7add hi-byte of pointer
0x8subtract hi-byte of pointer
0x9subtract lo-byte of pointer
0xAlogical AND with hi-byte of pointer
0xBlogical AND with lo-byte of pointer
0xClogical OR with hi-byte of pointer
0xDlogical OR with lo-byte of pointer
0xEexclusive OR with hi-byte of pointer
0xFexclusive OR with lo-byte of pointer
+

+ In some drum modes, the drum channel will always produce sound, even when no drum is triggered. This is due to the fact that the modifications + are applied before checking if the value read from memory is 0.


+
+
+ eof. +
+ + \ No newline at end of file diff --git a/font3.asm b/font3.asm new file mode 100644 index 0000000..aa9ee96 --- /dev/null +++ b/font3.asm @@ -0,0 +1,101 @@ +;compressed bitmaps for the font used by HT2. +;#87 bytes +;+ shifted: #,PLAY,STOP need not be shifted, so +#7d = #104... some other chars probably don't need shifting either, so should be possible to fit in a page +;moving G to the back, doesn't need shifting either. +;omitting V, can use STOre instead of SAVe. +;M doesn't need shifting move to back + + + db %01001010 ;0 + db %10101010 + db %01000100 ;....|1 + + db %11000100 + db %01001110 + + db %11000010 ;2 + db %01001000 + db %11101100 ;....|3 + + db %00100100 + db %00101100 + + db %10001010 ;4 + db %11100010 + db %00101100 ;....|5 + + db %10001100 + db %00101100 + + db %01001000 ;6 + db %11001010 + db %01001110 ;....|7 + + db %00100100 + db %01000100 + + db %01001010 ;8 + db %01001010 + db %01000100 ;....|9 + + db %10100110 + db %00100100 + + db %01101010 ;A + db %11101010 + db %10101100 ;....|B + + db %10101100 + db %10101100 + + db %01101000 ;C + db %10001000 + db %01101100 ;....|D + + db %10101010 + db %10101100 + + db %11101000 ;E + db %11001000 + db %11101110 ;....|F + + db %10001100 + db %10001000 + + db %10001000 ;10 - L + db %10001000 + db %11101100 ;....|N + + db %10101010 + db %10101010 + + db %11001010 ;12 - P + db %11001000 + db %10000110 ;....|S + + db %10000100 + db %00101100 + + db %11100100 ;14 - T + db %01000100 + db %01001010 ;....|# + + db %11101010 + db %11101010 + + db %00000000 ;16 - - + db %11100000 + db %00000110 ;....|G (17) + + db %10001010 + db %10101110 + + db %10101110 ;18 - M + db %11101010 + db %10100000 ;....|STOP (19) + + db %11101110 + db %11100000 + + db %10001100 ;PLAY (1a) + db %11101110 diff --git a/ht2.82p b/ht2.82p new file mode 100644 index 0000000..8e952bd Binary files /dev/null and b/ht2.82p differ diff --git a/ht2.83p b/ht2.83p new file mode 100644 index 0000000..f945e7c Binary files /dev/null and b/ht2.83p differ diff --git a/ht2.8xp b/ht2.8xp new file mode 100644 index 0000000..1014df2 Binary files /dev/null and b/ht2.8xp differ diff --git a/init.asm b/init.asm new file mode 100644 index 0000000..12c29a2 --- /dev/null +++ b/init.asm @@ -0,0 +1,393 @@ +;************************************************************************************ +;the startup code +;************************************************************************************ + +IF MODEL = TI82 || MODEL = TI8P +checkAPD_FREE ;check if APD_BUF is in use + ld a,(int_state) + or a + ret nz ;exit if it is. ->TODO: add error msg +ENDIF + +IF MODEL != TI83 + rom_call(clearlcd) +ENDIF + di + + push iy + push ix + + ld (exitSP),sp ;preserve stack + +;IF MODEL != TI8X ;setting ROM to a different page crashes TI83 +IF MODEL = TI82 + ld a,%10001001 ;set ROM page 1 + out (rom),a +ENDIF + +IF MODEL = TI8X + in a,(2) ;detect hardware + ld b,a + and #80 ;if bit 7 is set, we have TI83+ BASIC + jr z,reinit + + xor a + out (#20),a ;set 6 MHz mode + out (8),a ;disable link assist + + in a,(21h) + and 3 + jr z,usbdeact ;TI84+ SE + bit 5,b + jr z,reinit ;TI83+ SE + +usbdeact ;TI84+/SE detected, deactivating USB to save power + xor a + out (#57),a + out (#5b),a + out (#4c),a + ld a,2 + out (#54),a +ENDIF + +reinit + ld hl,apd_buf ;clear APD_BUF + ld de,apd_buf+1 + ld bc,767 + xor a + ld (hl),a + ldir + +;************************************************************************************ +generatePtnTabs ;generate pattern table and fx pattern table + + ld (_restSP),sp ;save stack pointer + ld sp,0+(256*((HIGH(graph_mem))+3)) + + ld de,#10 + ld hl,ptn00+(#7f*#10) ;HL = address of pnt #7f + ld b,#80 + +_lp + push hl ;push ptn address + sbc hl,de ;sub #10 + djnz _lp ;rinse and repeat + + ld sp,fxptntab+128 + sla e ;DE = #20 + ld hl,fxptn00+(#3f*#20) + ld b,#40 + +_lp2 + push hl + sbc hl,de + djnz _lp2 + +_restSP equ $+1 + ld sp,0 ;restore stack pointer + +;************************************************************************************ +generateCounterLUT ;generate note counter value table + + ld hl,baseCounterLUT ;copy BaseCounterLUT to APD_BUF + ld de,146+(256*((HIGH(apd_buf))+2)) ;unpacked font will be created on 3rd page of APD_BUF + ;length of LUT = 168 + 2 bytes (silence) + ld bc,24 + ldir ;ok + + ld hl,145+(256*((HIGH(apd_buf))+2)) ;start reverse calculation of lower octaves at [oct. 6]-1, de already points to last byte of LUT + ld b,#48 ;calculating 72 words + +_lp + dec e ;decrement source pointer (it's initially 1 too high from previous ldir) + xor a ;clear carry + ld a,(de) ;load hi byte + rra ;divide by 2 + ld (hl),a ;store + dec e ;decrement pointers + dec l + ld a,(de) ;load lo byte + rra ;divide by 2 and rotate in carry from hi byte + ld (hl),a ;store + dec l ;decrement target pointer + djnz _lp ;rinse and repeat + +;************************************************************************************ +generateCsrLUT ;generate cursor position table + ;LUT format: byte 1 = Horiz. + set bit 7 for #f0 cursor; byte 2 = vert. + ld c,10 ;10 rows + ld a,#87 ;first row vertical offset = #87 + ld hl,1+(256*((HIGH(graph_mem))+1)) ;start at 2nd page of graph_mem + 1 + +_lpo ;generate vertical positions + ld b,8 ;4*2 bytes per row +_lpi + ld (hl),a + inc l + inc l + djnz _lpi + add a,6 + dec c + jr nz,_lpo + + ld b,10 + ld l,0 ;reset LUT pointer + +_lp2 + ld a,#21 + ld (hl),a ;21 + inc l + inc l + add a,#81 ;inc a \ add a,#80 + ld (hl),a ;22+80 + inc l + inc l + inc a + ld (hl),a ;23+80 + inc l + inc l + sub #80 ;A-80 + ld (hl),a ;23 + inc l + inc l + inc a + ld (hl),a ;24 + inc l + inc l + add a,#81 + ld (hl),a ;25+80 + inc l + inc l + inc a + ld (hl),a ;26+80 + inc l + inc l + sub #80 + ld (hl),a ;26 + inc l + inc l + djnz _lp2 + +_generatePtnCsr ;generating pattern screen cursor positions at offset #50*2 + ld d,#21 + call fillTable + ld d,#22+#80 + call fillTable + ld d,#25 + call fillTable + ld d,#26+#80 + call fillTable + +_generateFxCsr ;generate fx screen cursor positions at text_mem + ld hl,CsrTab2 + ld d,#21+#80 + call fillTable + ld d,#21 + call fillTable + ld d,#22+#80 + call fillTable + ld d,#22 + call fillTable + ld d,#25+#80 + call fillTable + ld d,#25 + call fillTable + ld d,#26+#80 + call fillTable + ld d,#26 ;THIS CAUSES THE "LOW CONTRAST BUG" + call fillTable ;8 bytes is ok, 10 is too much - because it starts to write at #8000, d'uh + + jr unpackFont + +fillTable ;fill a chunk of the cursor position LUTs + ld b,8 + ld a,#93 +_lp + ld (hl),d + inc l + ld (hl),a + inc l + add a,6 + djnz _lp + ret + +;************************************************************************************ +unpackFont ;unpack the font + ld hl,font + ld de,256*((HIGH(apd_buf))+1) ;unpacked font will be created in APD_BUF (TI82 at #8300) + push de ;preserve pointer to unpacked font + + ld b,#45 ;unpacking 70 char bytes + or a ;clear carry + +unpackFontLP + ld a,(hl) ;load compressed char byte + and %11110000 + ld (de),a ;save unpacked byte + inc de ;increment pointer to unpacked font + ld a,(hl) ;load compressed char byte again + add a,a ;shift left 4 bits + add a,a + add a,a + add a,a + ld (de),a + inc de + inc hl + djnz unpackFontLP + + dec de ;last unpacked byte is irrelevant and can be overwritten + pop hl ;retrieve pointer to unpacked font + + ;create shifted chars + + ld b,#76 ;shifting #78 bytes (last 3 aren't needed) - TODO: need to exclude more chars from shifting so we don't cross page + ;ATTN! temporary skip last 2 bytes + or a ;clear carry + ;ld de,#81+256*((HIGH(apd_buf))+1) + +shiftFontLP + inc de ;de already points to end of unshifted chars + ld a,(hl) ;load unshifted pixel row + rra ;shift right 4 pixels + rra + rra + rra + ld (de),a + inc hl + djnz shiftFontLP + + +initSCR ;draw the basic screen layout + ld a,#f2 ;modify setXY code to use longer wait lp + ld (setXYmod),a + + ld de,#2080 ;select column 0, row 0 + call setXY ;set it + + ld a,7 ;cursor direction right + out (lcd_crt),a + call lcdWait3 + + ld b,#c ;12*8=96 pixel + ld a,#ff ;data to write + + call drawLoop ;draw a line on top of the screen + + ld de,#2981 + call setXY + + ld a,5 ;cursor direction down + out (lcd_crt),a + call lcdWait3 + + ld b,a ;ld b,5 + ld c,a ;preserve 5 in c because we'll need that constant a few more times + ld a,#ff + call drawLoop ;draw black block next to the logo + + ld de,#2881 + call setXY + + ld b,c ;ld b,5 + ld a,%00101111 + +_drawlp ;draw fancy block left of the black block + out (lcd_data),a + call lcdWait3 + sra a + djnz _drawlp + + ld de,#2a81 ;draw HT2 logo in the top right corner + call setXY + + ld hl,htlogo + ld b,c ;ld b,5 + call drawlp2 + + ld de,#2b81 + call setXY + + ld b,c ;ld b,5 + call drawlp2 + + ld a,#f4 ;modify setXY code to use shorter wait lp + ld (setXYmod),a + + +printVarNames ;create global var names on the right side + + ld de,#2988 ;update screen pointer + call setXY + + call clearPrintBuf + ld a,#19 ;print STOP char + call printCharLNC + + ld hl,varmsgs ;load chars + ;ld b,5 ;4 messages to print + ld b,4 + +_rdlp + ld d,(hl) + inc hl + ld e,(hl) + push hl + push bc + + call printDE ;print the chars held in DE + + pop bc + pop hl + inc hl + djnz _rdlp + + ld a,#d ;print a "D" (as in usr Drum) + call printCharL + + ld de,#0a01 ;print AutoInc indicator + call printDE + +p123D ;print channel active/mute info (123D) + call printMute12 + call printMute3D + + +;end of screen initialization +;************************************************************************************ + +printVars ;print global var names + + ld a,(looprow) ;temporary set loop point + call printCharsNoFF ;print them + + ld a,(speed) ;load global speed + call printCharsNoFF ;print + + ld a,(CPS) + call printCharsNoFF ;print + + ld a,(CPE) + call printCharsNoFF ;print + + ld a,(usrDrum) ;print lo byte of usr drum pointer + call printChars + + ld de,#2aa6 + call setXY + + ld a,(usrDrum+1) ;print hi byte of usr drum pointer + call printChars + +; checkSavestate +; ld a,(version) +; or a +; jr z,ldok +; ld a,#6 +; call errorHand +ldok + + + call printSeqScr ;print the main (sequence) screen + + call initSeqCsr ;init cursor + diff --git a/keyhand.asm b/keyhand.asm new file mode 100644 index 0000000..7861688 --- /dev/null +++ b/keyhand.asm @@ -0,0 +1,1839 @@ +;************************************************************************************ +;the key handler +;************************************************************************************ +inputSlotNr + ld a,#ef + out (kbd),a + key_delay + in a,(kbd) + rra + jr nc,ik0 + rra + jr nc,ik1 + rra + jr nc,ik4 + rra + jr nc,ik7 + + ld a,#f7 + out (kbd),a + key_delay + in a,(kbd) + rra + rra + jr nc,ik2 + rra + jr nc,ik5 + + ld a,#fb ;group (-)/3/6/9/)/G/VARS + out (kbd),a + key_delay + in a,(kbd) + rra + rra + jr nc,ik3 + rra + jr nc,ik6 + jr inputSlotNr + +ik0 + ld b,0 + jr kSlotSelect +ik1 + ld b,1 + jr kSlotSelect +ik2 + ld b,2 + jr kSlotSelect +ik3 + ld b,3 + jr kSlotSelect +ik4 + ld b,4 + jr kSlotSelect +ik5 + ld b,5 + jr kSlotSelect +ik6 + ld b,6 + jr kSlotSelect +ik7 + ld b,7 + + +kSlotSelect ;print state selection, and update it + ld de,#2bb2 + call setXY + + ld a,b + + ld (StateSelect),a ;store selected state + + jr reprint + ;call printCharL ;reprint current + + ;xor a + ;ld (InputType),a ;reset input type + + ;call printCsr ;print cursor + + ;jp waitForKeyRelease + +;************** + +inputSingle ;aka set current octave + + ld de,#2388 + call setXY + + ld a,b + cp 7 ;check if input digit is in range 0..6 + ret nc ;ignore keypress if it isn't + + ld (COct),a ;store new current oct + +reprint + call printCharL ;reprint current oct + + xor a + ld (InputType),a ;reset input type + + call printCsr ;print cursor + + ;ret + jp waitForKeyRelease + +inputDouble ;input a double digit hex value + ;IN: set iPrintPos and iUpdatePos + push af + +iPrintPos equ $+1 + ld de,0 + call setXY + +iUpdatePos equ $+1 + ld hl,0 + + pop af + rra + jr c,inputDoubleLow ;if input val=6, we're inputting the low nibble + + ld a,6 ;the next hex input should be a low nibble + ld (InputType),a + + ld a,b ;load input digit + push af + + add a,a + add a,a + add a,a + add a,a + + ld (hl),a + + pop af + call printCharL ;print it as upper nibble + +iDUpdate + jp waitForKeyRelease + ;ret + +inputDoubleLow + xor a ;reset input type + ld (InputType),a + + ld a,b + or (hl) + ld (hl),a + + call printCharsNoFF + + ld a,(CScrType) ;check what type of cursor to print + cp 2 + jr nz,_normal + call printCsr2 + jr wordSwitch-1 +_normal + call printCsr + +wordSwitch equ $+1 + ld a,0 + or a + jr z,iDUpdate + + xor a + ld (wordSwitch),a + + ld hl,usrDrum + ld de,#2ba6 + call setXY + call waitForKeyRelease + jp kSetBFull + + +inputWord + ex af,af' + ld a,1 + ld (wordSwitch),a + ex af,af' + jr inputDouble + + +kHexInp ;handle hex digit input + + ld b,a ;preserve the input value + + or a ;clear carry + ld a,(InputType) ;determine input type + rra + jp c,inputSingle + rra + jp c,inputDouble + rra + jp c,inputWord + + ld a,(CScrType) ;check screen type + or a + jp nz,kHexNoSeq + + call getSeqOffset ;now seq. pointer in HL, current ptn# in (CPtn) + + ld a,(AlphaFlag) ;check for Alpha mode + or a + jr z,_noalpha + ld a,b ;check if input char was 0 + or a + jr nz,_noalpha ;if both Alpha mode and 0, delete pattern # at cursor + + ld a,#ff + ld (hl),a + + jp pagescroll+3 + ;ld a,(CsrPos) + ;ld (OldCsrPos),a + ;call printSeqScr0 + ;call printCsr + ;jp waitForKeyRelease + +_noalpha + ld a,(CsrPos) ;check whether we need to shift the digit to upper nibble + rra + ld a,b ;retrieve input value + jr c,_noShift + add a,a ;shift left 4 bits + add a,a + add a,a + add a,a + ld b,a + ld a,(CPtn) ;load current ptn value + and %00001111 ;delete upper nibble + jr _byteUpdate + +_noShift + ld a,(CPtn) ;load current ptn value + and %11110000 ;delete lower nibble + +_byteUpdate + or b ;combine with input value + ld e,a ;preserve in E + + ld d,#7f ;make sure ptn# does not exceed #7f + ld a,(CsrPos) ;check column type + and 7 ;mask out bits that are irrelevant to horizontal pos + cp 6 + jr c,_skip ;if column > 5 + ld d,#3f ;we're setting fx ptn# - make sure it doesn't exceed #3f +_skip + ld a,e + and d + ld (hl),a ;and store it at song pointer + ld (CPtn),a + + call setPrintPos + call updateSeqScr + + ld a,(AutoInc) ;check AutoInc mode + or a + + ;jp z,kright + jp z,kRnoalpha ;if AutoInc mode is on, update cursor as if RIGHT key had been pressed + jp printCsr ;else, simply reprint the cursor at the current position + + +updateSeqScr ;update an entry on the sequence screen + ld a,(CsrPos) ;load cursor pos + and 3 ;check what type of column is being printed + cp 0 ;and select the print function accordingly + jr z,uRight + cp 1 + jr z,uLeft + +uBoth + ld a,(CPtn) + jp printChars + ;ret + +uRight + ld a,(CPtn) + push de + call printCharR + pop de + inc d + call setXY + ld a,(CPtn) + jp printCharL + ;ret + +uLeft + ld a,(CPtn) + push de + call printCharL + pop de + dec d + call setXY + ld a,(CPtn) + jp printCharR + ;ret + +;************************************************************************************ +kHexNoSeq ;handling input on ptn screen + ;IN: B=hex digit + dec a ;check if we're on an fx ptn screen + jp nz,kHexFX + +kHexPtn + call findCurrPtn ;get ptn pointer into DE + ld h,0 + ld a,(CsrPos) ;get cursor position + ld c,a ;preserve it in C + sub #50 + and %11110111 ;mask out bit 3 + cp #f ;if cursor pos is in 2nd column + jr c,_skip + ;rra ;divide it by 2 to get values 8..F + sub 8 +_skip + ld l,a + add hl,de ;position to edit now referenced by HL + push hl ;a08a + + ld a,c ;retrieve cursor position and determine if input is a note name or an octave + and 8 + ld a,b ;retrieve input digit + jr nz,inputOct + +inputNote + or a + jr z,_exitlp + + cp #a ;check if input digit is A..G... handle G seperatly? + jp c,ignoreKeypress ;ignore keypress if it isn't + + ld c,a ;preserve input digit in C + + ld hl,notevals ;load note val conversion LUT pointer + add a,l ;add offset + ld l,a + + ld a,(COct) ;fetch current octave + ld b,a + inc b + + ld a,(AlphaFlag) ;check if ALPHA mode is active + or a + jr z,_skip ;if it is + + ld a,#b ;check if input note was a B + sub c + jr z,_skip ;skip raising halftone if it was + + ld a,1 ;add a half-tone (TODO: check if it's a valid halftone - or ignore and always go a halftone higher, also fine) +_skip + add a,(hl) ;get base note val + ld c,a ;preserve it in C +_lp + dec b + jp z,_exitlp + add a,12 + jr _lp + +_exitlp ;note val now in A + pop hl + ld (hl),a ;update note byte + or a + jr z,_reprintDash + +_reprint + call setPrintPos + + push de + + ld a,c ;restore base note val + dec a ;note names are offset by 1, correct it + ld hl,notenames ;point to note name LUT + add a,a ;A=A*2 + ld e,a + ld d,0 + add hl,de ;add offset to LUT pointer + + ld d,(hl) ;get string into DE + inc hl + ld e,(hl) + + call printDE + pop de ;retrieve print pos + inc d ;inc horiz. pos by 1 + call setXY + + ld a,(COct) ;print current octave + call printCharL + + ld a,(RowPlay) + or a + jr z,_skipRP + call rowPlay + +_skipRP + ld a,(AutoInc) + or a + jp z,kpdown ;and update cursor as if DOWN key has been pressed + jp printCsr + + +_reprintDash ;print dashes if new note byte = 0 + call setPrintPos + push de + + ld de,#1616 + call printDE + + pop de + inc d + call setXY + + call clearPrintBuf + ld a,#16 + call printCharLNC + + ;jp kpdown + jr _skipRP + + +inputOct + pop hl + cp 7 ;check if input digit is 0..6 + jp nc,ignoreKeypress+1 ;ignore keypress if it isn't + push bc + + ld a,(hl) ;load current note val + or a ;if no note is set + jp z,ignoreKeypress ;ignore keypress + + call divNoteVal ;returns current octave in B, base note val in C + + ld a,c + pop bc + ld c,b ;preserve input digit (new octave) in C + inc b + +_lp + dec b + jr z,_skip + add a,12 ;for each octave >0, add 12 to base note val + jr _lp +_skip + inc a ;note vals are offset by 1 + ld (hl),a ;store new load value + + call setPrintPos + + ld a,c ;retrieve input digit (new oct) + + call printCharL ;print it + + jp kpdown ;and update cursor as if DOWN key has been pressed + + +;************************************************************************************ +kHexFX ;handle hex input on fx ptn scr + ;IN: B=hex digit + + ld a,(CPtn) ;locate current fx ptn in mem + ld hl,fxptntab + call findCurrFxPtn ;ptn pointer now in DE + + ld hl,0 + ld a,(CsrPos) ;read cursor position and convert it to ptn data offset + ld c,a ;backup in C + and %011110111 ;mask out bit 3 and 7 since they're irrelevant + add a,a ;in fx ptns, each row takes 2 bytes + cp #20 + jr c,_skip3 + ld l,#1f + + cp #40 + jr c,_skip3 + ld l,#30 + + cp #60 + jr c,_skip3 + ld l,#4f +_skip3 + sub l + ld l,a + + add hl,de ;byte to edit now referenced by HL + + ld a,c ;restore csrpos + and %00001000 ;determine whether input is hi or low nibble + ld a,b ;restore input val + jr nz,_skip ;if Z then it's a hi nibble + add a,a ;shift input value left 4 bits + add a,a + add a,a + add a,a + ld b,a + ld a,(hl) + and %00001111 ;clear upper nibble + jr _set +_skip + ld a,(hl) + and %11110000 ;clear lower nibble +_set + or b ;combine low and hi nibble + ld (hl),a + + ld c,a + ld hl,CsrTab2 + call setPrintPosFx + ld a,c + + call printCharsNoFF + + ld a,(AutoInc) + or a + jp z,kfdown + jp printCsr2 ;TODO: this bugs + +ignoreKeypress + pop hl ;clear stack + ret ;and back to where we came from + +;************************************************************************************ +setPrintPos ;set print position based on current cursor pos + ;IN: nothing | OUT: print pos set and in DE; HL, A destroyed + ld hl,CsrTab +setPrintPosFx ;entry point for FX patterns, HL must be set to CsrTab2 + ld a,(CsrPos) + add a,a + add a,l + ld l,a + ld a,(hl) + and %01111111 ;mask out bit 7 since cursor type is irrelevant at this point + ld d,a + inc l + ld a,(hl) + sub 5 ;actual horiz. pos = CsrPos - 5 + ld e,a + jp setXY ;using the ret from setXY + +;************************************************************************************ +kfdown + call delCsr2 ;delete cursor + ld a,(CsrPos) + inc a ;jump to next row + ld d,a + and %00000111 + or a + ld a,d + jr nz,kdirskipF ;if bottom row reached + add a,#18 ;jump to top of same column, 2nd half + cp #40 + jr c,kdirskipF ;if bottom row on 2nd half reached + sub #40 ;jump to top of same colum, 1st half + +kdirskipF + ld (CsrPos),a + call printCsr2 + jp waitForKeyRelease + ;ret + +kfleft + ld a,(AlphaFlag) ;check Alpha mode + or a + jr z,_noalpha + ;if Alpha is on, cycle through patterns + ld de,#2382 ;TODO: optimize | set printing pos + call setXY + + ld a,(CPtn) ;increment "current pattern" value + dec a + and #3f ;make sure we don't go above #7f + ld (CPtn),a + + jp printFxScrNoInit ;and print the new pattern + +_noalpha + call delCsr2 ;delete cursor + ld a,(CsrPos) + sub 8 ;jump to previous column + jr nc,kdirskipF ;if already in the 1st column + add a,#40 ;wrap to last column + jr kdirskipF + +kfright + ld a,(AlphaFlag) ;check Alpha mode + or a + jr z,_noalpha + ;if Alpha is on, cycle through patterns + ld de,#2382 ;TODO: optimize | set printing pos + call setXY + + ld a,(CPtn) ;increment "current pattern" value + inc a + and #3f ;make sure we don't go above #7f + ld (CPtn),a + + jp printFxScrNoInit ;and print the new pattern + +_noalpha + call delCsr2 ;delete cursor + ld a,(CsrPos) + add a,8 ;jump to next column + cp #40 + jr c,kdirskipF ;if already in the last column + sub #40 ;wrap to first column + jr kdirskipF + +kfup + call delCsr2 + ld a,(CsrPos) + dec a + ld d,a + and %00000111 + cp #7 + ld a,d + jr nz,kdirskipF + sub #18 ;#ff-#18 doesn't set carry, + or a ;so we need to check if result was negative + jp p,kdirskipF ;like that + add a,#40 + jr kdirskipF + + +kpdown + call delCsr ;delete cursor + ld a,(CsrPos) + inc a ;jump to next row + ld d,a + and %00000111 + or a ;TODO: redundant? + ld a,d + jp nz,kdirskip ;if bottom row reached + add a,#8 ;jump to top of same column, 2nd half + cp #70 + jp c,kdirskip ;if bottom row on 2nd half reached + sub #20 ;jump to top of same colum, 1st half + jp kdirskip + +kpleft + ld a,(AlphaFlag) ;check Alpha mode + or a + jr z,_noalpha + ;if Alpha is on, cycle through patterns + ld de,#2382 ;TODO: optimize | set printing pos + call setXY + + ld a,(CPtn) ;increment "current pattern" value + dec a + and #7f ;make sure we don't go above #7f + ld (CPtn),a + + jp printPtnScrNoInit ;and print the new pattern + +_noalpha + call delCsr + ld a,(CsrPos) + sub 8 + cp #50 + jp nc,kdirskip + add a,#20 + jp kdirskip + +kpright + ld a,(AlphaFlag) ;check Alpha mode + or a + jr z,_noalpha + ;if Alpha is on, cycle through patterns + ld de,#2382 ;TODO: optimize | set printing pos + call setXY + + ld a,(CPtn) ;increment "current pattern" value + inc a + and #7f ;make sure we don't go above #7f + ld (CPtn),a + + jp printPtnScrNoInit ;and print the new pattern + +_noalpha ;do normal cursor movement + call delCsr + ld a,(CsrPos) + add a,8 + cp #70 + jp c,kdirskip + sub #20 + jp kdirskip + +kpup + call delCsr + ld a,(CsrPos) + dec a + ld d,a + and %00000111 + cp #7 + ld a,d + jp nz,kdirskip + sub #8 + cp #50 + jp nc,kdirskip + add a,#20 + jp kdirskip + +kup + ld a,(CsrPos) + ld (OldCsrPos),a + ld a,(AlphaFlag) + or a + jr z,kuskip + xor a + ld (FirstLineMS),a + call printSeqScr + jp kdirskip2 + +kuskip + call delCsr ;delete cursor + ld a,(CsrPos) + sub 8 ;subtract 8 from cursor pos + jp nc,kdirskip ;and that's it, unless cursor is about to go off-screen + + ld a,(FirstLineMS) ;in that case, check what's the first line of sequence data on screen + or a + jp z,kdirskip2 ;if it's 0, don't change anything and that's it + + dec a ;else, decrement FirstLine + ;ld (FirstLineMS),a ;and store it + ;call printSeqScr0 ;reprint sequence screen (without setting screen type / kdir jump table offset) + ;jp kdirskip2 + jr seqScrReprint + +kright + ld a,(AlphaFlag) ;check for Alpha mode + or a + jr z,kRnoalpha + ld a,(FirstLineMS) ;if Alpha mode is set, scroll 1 page (10 lines) + add a,#a ;add 10 to FirstLine +pagescroll0 + cp #f7 + jr c,pagescroll ;if result is >#f6 + ld a,#f6 ;set FirstLine to #f6 +pagescroll + ld (FirstLineMS),a +reprintX + ld a,(CsrPos) + ld (OldCsrPos),a + call printSeqScr0 + call printCsr + jp waitForKeyRelease + +kRnoalpha + call delCsr + ld a,(CsrPos) + inc a + cp #50 ;check if cursor pos limit reached + jr nz,kdirskip + ;xor a + ld a,#48 ;if yes, move cursor to beginning of the same row + ld (OldCsrPos),a + jr kdskip+3 ;and scroll screen + +kdown + ld a,(CsrPos) + ld (OldCsrPos),a + ld a,(AlphaFlag) + or a + jr z,kdskip + + ld a,#f6 + ld (FirstLineMS),a + call printSeqScr + jr kdirskip2 + +kdskip + call delCsr + ld a,(CsrPos) + add a,8 + cp #50 + jr c,kdirskip + + ld a,(FirstLineMS) ;need to implement scroll/wrap here + cp #f6 ;#100 - 0a + jr z,kdirskip2 + + inc a +seqScrReprint + ld (FirstLineMS),a + call printSeqScr0 + jr kdirskip2 + +kleft + ld a,(AlphaFlag) ;check for Alpha mode + or a + jr z,_noalpha + ld a,(FirstLineMS) ;if Alpha mode is set, scroll 1 page (10 lines) + sub #a + jr pagescroll0 + +_noalpha + call delCsr + ld a,(CsrPos) + sub 1 + jr nc,kdirskip + ;ld a,#4f + ld a,7 + ld (OldCsrPos),a + jp kuskip+3 + + +kdirskip + ld (CsrPos),a +kdirskip2 + call printCsr +kdirskip3 + jp waitForKeyRelease + ;ret + +kdir ;determine which direction key has been pressed + rra + jr nc,_kp + inc d + jp kdir +_kp + ld h,HIGH(kjumptab) ;set hi byte of jump table pointer +kdirswitch equ $+1 ;switch for changing the response to keypress according to ptn type + ld a,LOW(kjumptab) + add a,d ;add D*2 + add a,d + ld l,a ;set lo byte of jump table pointer + ld e,(hl) ;get jump value into DE + inc l + ld d,(hl) + ex de,hl ;swap jump value into HL + + jp (hl) ;and jump + + +;************************************************************************************ +keyhand ;the main keyhandler + + ld a,#fe ;group dirpad + out (kbd),a +IF MODEL != TI82 + nop + nop +ENDIF + ld e,#ff + ld d,0 + in a,(kbd) + cp e + jr nz,kdir + + ld a,#fd ;group ENTER/+/-/*/div/CLEAR + out (kbd),a + ;nop + ;nop + key_delay + in a,(kbd) + rra ;ENTER + jp nc,kenter + rra + jp nc,kplus ;+ + rra + jp nc,kminus ;- + rra + jp nc,kmult ;* + rra + jp nc,kdiv ;/ + rra + jp nc,kpot ;^ + rra + jp nc,kclear ;CLEAR + + ld a,#fb ;group (-)/3/6/9/)/G/VARS + out (kbd),a + ;nop + ;nop + key_delay + in a,(kbd) + rra + jp nc,kneg + rra + jp nc,k3 + rra + jp nc,k6 + rra + jp nc,k9 + rra + jp nc,kcbracket + rra + jp nc,kG + rra + jp nc,kvars + + ld a,#f7 + out (kbd),a + ;nop + ;nop + key_delay + in a,(kbd) + rra + jp nc,kdot + rra + jp nc,k2 + rra + jp nc,k5 + rra + jp nc,k8 + rra + jp nc,kobracket + rra + jp nc,kF + rra + jp nc,kC + rra + jp nc,kstat + + ld a,#ef + out (kbd),a + ;nop + ;nop + key_delay + in a,(kbd) + rra + jp nc,k0 + rra + jp nc,k1 + rra + jp nc,k4 + rra + jp nc,k7 + rra + jp nc,kcomma + rra + jp nc,kE + rra + jp nc,kB + rra + jp nc,kxto + + ld a,#df + out (kbd),a + ;nop + ;nop + key_delay + in a,(kbd) + rla + jr nc,kalpha + rla + jr nc,kA + rla + jr nc,kD + rla + jr nc,kxsq + rla + jr nc,klog + rla + jr nc,kln + rla + jr nc,ksto + + ld a,#bf + out (kbd),a + ;nop + ;nop + key_delay + in a,(kbd) + rra + jp nc,kgraph + rra + jp nc,ktrace + rra + jp nc,kzoom + rra + jp nc,kwindow + rra + jp nc,kyeq + rra + jp nc,k2nd + rra + jp nc,kmode + rra + jp nc,kdel + + ld a,(AlphaFlag) ;check ALPHA mode + or a + ret z ;exit keyhandler if not set (ignoring ON key) + + in a,(kon) ;check ON key + and %00001000 + jp z,exit + ret ; + + +;************************************************************************************ +kalpha + ld de,#2888 + call setXY + + ld a,(AlphaFlag) + xor #a0 + ld (AlphaFlag),a ;set AlphaFlag + + or a + jr z,_skip + + call printCharR ;print Alpha mode marker +_skip0 + jp waitForKeyRelease + ;ret + +_skip + call clearPrintBuf ;clear print buffer + call printBuf ;remove Alpha mode marker from screen + jr _skip0 + +kA + ld a,#0a + jp kHexInp +kD + ld a,#0d + jp kHexInp + +kxsq ;set loop point + ld hl,looprow + ld de,#2b8e + jr kBSet + +klog + ret +kln ;set BS + ld hl,CPS + ld de,#2b9a + jr kBSet + +ksto ;set BE + ld hl,CPE + ld de,#2ba0 + +kBSet + call setXY + + ld a,(AlphaFlag) + or a + jr nz,kSetBFull ;if ALPHA mode is set, do a regular set BT + +kSetBlock + ld a,(CScrType) ;check screen type + or a + ret nz ;for now, ignore keypress if not on main screen TODO: implement alternative for ptn screens + + ld a,(FirstLineMS) ;calculate current line + ld b,a + ld a,(CsrPos) + rra ;on-screen row# = (CsrPos/8 AND %00001111) + rra + rra + and #f + add a,b ;absolute row# in sequence = first on-screen row# + current on-screen row# + ld (hl),a + + call printChars +exitthis + ;call waitForKeyRelease + ;ret + jp waitForKeyRelease + +kSetBFull + ld a,2 ;set InputType to signal 2-digit hex input + ld (InputType),a + ;ld hl,CPT + ld (iUpdatePos),hl ;set position in memory to update + ex de,hl + ld (iPrintPos),hl ;set print position + + call clearPrintBuf + call printBuf + + ld a,(CScrType) ;check what type of cursor to delete + cp 2 + jp nz,delCsr + jp delCsr2 +;***** +kgraph ;set current Octave + + ld a,(CScrType) ;check screen type + dec a + ret nz ;if not on a ptn screen, ignore keypress + ld a,1 + ld (InputType),a + + ld de,#2388 + call setXY + call clearPrintBuf + call printBuf + + jp delCsr ;temporarily disable cursor + +ktrace + ld a,(AlphaFlag) + or a + jr nz,setUsrDrumHi + + ld hl,speed + ld de,#2b94 + call setXY + jp kSetBFull + +setUsrDrumHi + ld hl,usrDrum+1 + ld de,#2aa6 + call setXY + ld a,4 + jp kSetBFull+2 + ;jp kSetBFull + +setUsrDrumLo + ld hl,usrDrum + ld de,#2ba6 + call setXY + jp kSetBFull + +kzoom + ret +kwindow ;delete save slot / clear current tune + + ld a,(PlayerFlag) ;check if player is running - actually unnecessary, should be save to save while player is running + or a + ret nz ;if it is, ignore command + + ld a,(AlphaFlag) ;check alpha flag + or a + jr z,_zap + call delSlot + jp waitForKeyRelease + ;jp nz,delSlot ;if Alpha mode is active, delete save slot + ;else, clear current tune +_zap + ld de,#0c0a ;print "CA" message + call printMsg + call confirmAction + jp c,exitthis + + pop hl + call zap + jp reinit + +kyeq ;load + ld a,(PlayerFlag) ;check if player is running - actually unnecessary, should be save to save while player is running + or a + ret nz ;if it is, ignore command + ld de,#100d ;LD message + ld a,(AlphaFlag) + or a + jr z,_skip + ld de,#130a ;SA message +_skip + call printMsg + call stateSelect + call confirmAction + jp c,exitthis + + ld a,(AlphaFlag) + or a + jp nz,save + + pop hl ;pop return address from stack + call load ;load song + jp reinit ;reinit HT2 + +k2nd + ld a,(CScrType) ;check if we're on a pattern screen + or a + jr nz,_retPtnS + call clrS ;clear screen + ld a,(CsrPos) ;determine whether to print normal or fx pattern + ld (OldCsrPos),a + and %00000110 + cp 6 + jp nz,printPtnScr + jp printFxScr + +_retPtnS + call printSeqScr + call initSeqCsr + jp waitForKeyRelease + ;ret +kmode ;switch AutoInc/RowPlay mode + ld a,(AlphaFlag) + or a + jr nz,_toggleRP + + ld de,#29ac + call setXY + + ld a,(AutoInc) + xor 1 + ld (AutoInc),a + + xor 1 + ld e,a + ld d,#a + + call printDE + + jp waitForKeyRelease + +_toggleRP + ld de,#2aac + call setXY + + ld a,(RowPlay) + cpl + ld (RowPlay),a + + or a + jr z,_skipx + call clearPrintBuf + ld a,#12 + call printCharLNC + jp waitForKeyRelease + +_skipx + call clearPrintBuf ;clear print buffer + call printBuf + jp waitForKeyRelease + +kdel + ret +k0 + xor a + jp kHexInp +k1 + ld a,1 + jp kHexInp +k4 + ld a,4 + jp kHexInp +k7 + ld a,7 + jp kHexInp + +kcomma ;mute ch1 + ld a,(AlphaFlag) + or a + jr nz,_unmuteAll + ld a,(MuteState) ;toggle flag bit 0 + xor 1 + ld (MuteState),a + ld a,(mute1) ;toggle mute switch + xor #28 + ld (mute1),a + call printMute12 + jp waitForKeyRelease + +_unmuteAll + xor a + ld (MuteState),a + ld a,#9f + ld (mute2),a + ld (mute3),a + ld a,#30 ;#30 jr nc / #18 jr + ld (mute1),a + ld (muteD),a + call printMute12 + call printMute3D + jp waitForKeyRelease + + +kE + ld a,#0e + jp kHexInp + +kB + ld a,#0b + jp kHexInp + +kxto ;transpose + ld a,(CScrType) + dec a ;checking if we're currently on a note pattern screen + jp nz,waitForKeyRelease + + call findCurrPtn ;pattern pointer now in DE + + ld b,#10 ;16 notes to transpose + + ld a,(AlphaFlag) + or a + jr nz,_transposeDown + +_transposeUp + ld a,(de) + or a ;check for rest (#00) + jr z,_notranspose + inc a ;transpose up by 1 halftone + cp #55 ;check for upper limit (#00) + jr nz,_notranspose + xor a ;replace with if upper limit crossed + +_notranspose + ld (de),a + inc de + djnz _transposeUp + +_done + jp printPtnScrBasic + + +_transposeDown + ld a,(de) + dec a + cp #ff + jr nz,_notranspose2 + xor a + +_notranspose2 + ld (de),a + inc de + djnz _transposeDown + + jp printPtnScrBasic + + + ;ret +kdot + ret +k2 + ld a,2 + jp kHexInp +k5 + ld a,5 + jp kHexInp +k8 + ld a,8 + jp kHexInp + +kobracket + ld a,(AlphaFlag) + or a + jr nz,kMuteD + + ld a,(MuteState) ;toggle flag bit 1 + xor 2 + ld (MuteState),a + ld a,(mute2) + xor #8 ;toggle between jr nc and unconditional jr + ld (mute2),a + call printMute12 + jp waitForKeyRelease + +kMuteD + ld a,(MuteState) ;toggle flag bit 7 + xor #80 + ld (MuteState),a + ld a,(muteD) + xor #28 + ld (muteD),a + call printMute3D + jp waitForKeyRelease + + + +kF + ld a,#0f + jp kHexInp +kC + ld a,#0c + jp kHexInp +kstat +kneg ;play from current row + ld a,(PlayerFlag) + or a + jp nz,waitForKeyRelease + + ld (exitPlayerSP),sp ;store SP for exiting player + inc a ;set player flag, A=1 + ld (PlayerFlag),a + + ld de,#2988 ;update screen pointer + call setXY + call clearPrintBuf + ld a,#12 ;print P for PLAY + call printCharLNC + + call waitForKeyRelease + + xor a + ld h,a + ld d,a + ld a,(CScrType) ;if on seq.screen + or a + ld a,(CsrPos) ;derive current sequence line from (CsrPos) + jr z,_skip + ld a,(OldCsrPos) ;else, derive it from (OldCsrPos) +_skip + call findCurrLineNoSeq ;find current line in sequence + ex de,hl ;get pointer into DE + + call initrp ;call player + jp exitplayer + +k3 + ld a,3 + jp kHexInp +k6 + ld a,6 + jp kHexInp +k9 + ld a,#09 + jp kHexInp + +kcbracket + ld a,(AlphaFlag) + or a + jr nz,_muteAll + ld a,(MuteState) ;toggle flag bit 6 + xor #40 + ld (MuteState),a + ld a,(mute3) ;toggle between sbc a,a and sub a + xor #8 + ld (mute3),a + call printMute3D + jp waitForKeyRelease + +_muteAll + ld a,%11000011 + ld (MuteState),a + ld a,#97 + ld (mute2),a + ld (mute3),a + ld a,#18 ;#30 jr nc / #18 jr + ld (mute1),a + ld (muteD),a + call printMute12 + call printMute3D + jp waitForKeyRelease + + +kG + ld a,(CScrType) ;check screen type + cp 1 + ret nz ;ignore keypress if not on a note ptn screen + ld b,#10 + jp kHexPtn +kvars + ret + +kminus + ld a,(CScrType) ;detect current screen type + or a + jp nz,waitForKeyRelease ;and exit if not on sequence screen + + call findCurrLine ;get pointer to current line into HL + + xor a ;clear carry + ld de,ptn00-5 ;point DE to end of ptn sequence - 5 + ex de,hl + sbc hl,de ;end - 5 - current line = copy length + push hl ;get it into bc + pop bc + + ld a,(AlphaFlag) ;check if we're inserting or deleting + or a + ;jr nz,_deleteline + jr nz,_reprint + + ld hl,ptn00-6 ;source = end of sequence - 4 + ld de,ptn00-2 ;dest = end of sequence + lddr ;copy stuff + +_reprint + call printSeqScr0 + call printCsr + jp waitForKeyRelease + +_deleteline + push de ;DE already holds destination, copy into HL + pop hl + inc hl ;source = HL + 4 + inc hl + inc hl + inc hl + ldir ;copy stuff + ld b,4 ;fill last 4 bytes of sequence with #ff + ld a,#ff + ld hl,ptn00-5 +_lp + ld (hl),a + inc hl + djnz _lp + jr _reprint + + +kplus ;insert next free pattern value at cursor + ld a,(CScrType) ;detect current screen type + or a + jp nz,waitForKeyRelease ;and exit if not on sequence screen + + call getSeqOffset ;get source pattern # and save it for later use + ld (SourcePtn),a + + ld a,(CsrPos) + and %00000110 + cp 6 + jr z,insertFxPtn + + xor a +_chklp + call findNextUnused + jr z,noFreePtn + push af + call isPtnFree + jr z,freeFound + pop af + inc a + cp #80 ;check if all patterns have been searched + jr nz,_chklp + +noFreePtn ;handling error if no free ptns found + ld a,7 + jp errorHand + +freeFound + call getSeqOffset + pop af + ld (hl),a + + ld a,(AlphaFlag) ;check for Alpha mode + or a + jr z,_return + + ld a,(SourcePtn) ;if in Alpha mode, copy source pattern to new pattern + cp #ff ;unless source pattern was empty (#ff) + ;jr z,_return + jp z,reprintX + + ld a,(CsrPos) + and %00000110 + cp 6 + ld a,(hl) + jr z,_copyfx + + call findPtn ;find the current pattern in memory - pointer is now in DE + push de ;preserve pointer to it + + ld a,(SourcePtn) + call findPtn ;find source pattern in memory + ex de,hl ;put pointer to it in HL + pop de ;retrieve source pointer + + ld bc,#10 ;copy pattern +_copy + ldir + +_return + jp reprintX +; ld a,(CsrPos) +; ld (OldCsrPos),a +; call printSeqScr0 +; call printCsr +; jp waitForKeyRelease + +_copyfx + ld hl,fxptntab + call findCurrFxPtn + push de + + ld a,(SourcePtn) + ld hl,fxptntab + call findCurrFxPtn + ex de,hl + pop de + + ld bc,#20 + jr _copy + + +insertFxPtn + xor a +_chklp + call findNextUnusedFX + jr z,noFreePtn + push af + call isFxPtnFree + jr z,freeFound + pop af + inc a + cp #40 + jr nz,_chklp + + +kmult ;copy/paste block + ld a,(CScrType) ;detect current screen type + or a + jp nz,waitForKeyRelease ;and exit if not on sequence screen + + ld a,(CPS) ;verify that Block End >= Block Start + exx + ld d,a + exx + ld b,a + ld a,(CPE) + exx + ld e,a + exx + sub b + ld b,a ;save block length - 1 in B + ld a,1 + jp c,errorHand ;and output error if it isn't + + call getCurrLineNo + ld c,a + + inc a ;check that curr line + block length <= #ff + add a,b + ld a,8 + jp c,errorHand + + ld a,(CPS) + sub c + jr nc,_insertBefore ;if BS >= curr line, we're inserting before the selection + ld a,(CPE) + sub c + jr c,_insertAfter ;if curr line > BE, we're inserting after the selection + ld a,1 ;else, curr line is within selection -> output error + jp errorHand + + +_insertBefore + ;ld a,(AlphaFlag) ;check Alpha mode + ;or a + ;jr nz,_paste ;and skip pre-shifting data if in Alpha mode + push bc + exx + pop bc + inc b + ld a,d + add a,b + ld d,a + ld a,e + add a,b + ld e,a + exx + + +_insertAfter + ld a,(AlphaFlag) ;check Alpha mode + or a + jr nz,_paste ;and skip pre-shifting data if in Alpha mode + call calculateCopyParams ;calculate Block start, length, current line # + + ld hl,ptn00-2 ;calculate shift block params + or a ;clear carry + sbc hl,bc ;source now in HL + push hl + + call findCurrLine ;current line start now in HL + + ex de,hl ;current line start now in DE + + pop hl ;retrieve source pointer + push hl + + xor a + sbc hl,de ;copy block length = source - current line start + 1 + inc hl + ld b,h + ld c,l ;copy block length now in BC + + pop hl ;retrieve source pointer + ld de,ptn00-2 ;set dest. pointer + + lddr ;shift block + +_paste + call calculateCopyParams ;calculate Block start, length, current line # + push bc + + ld l,a ;calculate copy destination + ld h,0 + add hl,hl + add hl,hl ;copy destination - base offset now in HL + ld bc,ptns + add hl,bc + ex de,hl ;copy destination now in DE + + add hl,bc ;block start now in HL + pop bc + ldir + + jp reprintX +; _reprint +; ld a,(CsrPos) +; ld (OldCsrPos),a +; call printSeqScr0 +; call printCsr +; jp waitForKeyRelease + +kdiv ;deleting rows and blocks + ld a,(CScrType) + or a + jp nz,waitForKeyRelease + + ld a,(AlphaFlag) ;check for Alpha mode + or a + jr nz,_deleteBlock + +_deleteRow + call findCurrLine ;pointer to current line start = dest now in HL + push hl + ld de,ptn00-5 ;copy block length = seq.end - curr.line + 4 + ex de,hl + sbc hl,de + ld b,h + ld c,l ;copy block length now in BC + pop hl ;retrieve dest + ld d,h ;dest now in DE + ld e,l + inc hl ;source = dest + 4 + inc hl + inc hl + inc hl + ldir ;copy stuff + + ld b,4 ;clean up sequence end + ld hl,ptn00-5 + ld a,#ff +_lp + ld (hl),a + inc hl + djnz _lp + + +_reprint +; ld a,(CsrPos) +; ld (OldCsrPos),a +; call printSeqScr0 +; call printCsr +; jp waitForKeyRelease + jp reprintX + +_deleteBlock + ld a,(CPS) ;verify that Block End >= Block Start + ld b,a + ld a,(CPE) + sub b + ld l,a ;save block length (lines) - 1 in L + ld a,1 + jp c,errorHand ;output error if BS/BE invalid + + ld h,0 ;calculate block length in memory + inc hl ;adjust length (always 1 line more than calculated) + add hl,hl + add hl,hl + + push hl ;block length now in HL + + ld bc,ptns + ld a,(CPS) ;target = (CPS)*4 + ptns + ld h,0 + ld l,a + add hl,hl + add hl,hl + add hl,bc + ex de,hl ;target now in DE + + ld a,(CPE) ;source = (CPE+1)*4 + ptns + inc a + ld h,0 + ld l,a + add hl,hl + add hl,hl + add hl,bc ;source now in HL + + push hl + push de + ex de,hl + + ld hl,ptn00-1 ;copy length = ptns.end - source +1? + xor a + sbc hl,de + ld b,h + ld c,l + + pop de + pop hl + ldir + + pop bc ;retrieve block length into bc + ld hl,ptn00-2 + +_lp2 + ld a,#ff + ld (hl),a + dec hl + dec bc + ld a,b + or c + jr nz,_lp2 + + ;jr _reprint + jp reprintX + +kpot +kclear + ret + + +kenter + ld a,(PlayerFlag) ;check if player is running + or a + jr nz,exitplayer + + ld (exitPlayerSP),sp ;store SP for exiting player + ;ld a,1 ;set player flag + inc a ;set player flag, A=1 + ld (PlayerFlag),a + + ld de,#2988 ;update screen pointer + call setXY + call clearPrintBuf + ld a,#12 ;print P for PLAY + call printCharLNC + + call mplay ;call the music player + +exitplayer +exitPlayerSP equ $+1 + ld sp,0 ;restore stack + xor a ;reset player flag + ld (PlayerFlag),a + ld a,lp_off ;turn off sound + out (link),a + + ld de,#2988 ;update screen pointer + call setXY + call clearPrintBuf + ld a,#19 ;print STOP char + call printCharLNC + + jp waitForKeyRelease + ;ret ;return to keyhandler diff --git a/main.asm b/main.asm new file mode 100644 index 0000000..bba3a96 --- /dev/null +++ b/main.asm @@ -0,0 +1,1381 @@ +;************************************************************************************ +;HOUSTONTRACKER 2.00 +;by utz * irrlichtproject.de/houston +;************************************************************************************ + +;************************************************************************************ +;OS/shell settings +;************************************************************************************ + +TI82 EQU 1 +TI83 EQU 2 +TI8X EQU 3 +TI8P EQU 4 + +IF MODEL = TI82 +include "_include/ti82.inc" +ENDIF + +IF MODEL = TI8P +include "_include/ti82parcus.inc" +ENDIF + +IF MODEL = TI83 +include "_include/ti83.inc" +ENDIF + +IF MODEL = TI8X +include "_include/ti8xp.inc" +ENDIF + + db "HT 2.00", 0 + +;************************************************************************************ +;APD_BUF scratch pad and other equates + + +CharString equ apd_buf+#00 ;2 2 character codes for printing +FirstLineMS equ apd_buf+#02 ;1 first line of sng sequence to be displayed on main screen +CPS equ apd_buf+#03 ;1 start of copy block +CPE equ apd_buf+#04 ;1 end of copy block + +SourcePtn equ apd_buf+#05 ;1 number of the source pattern (for copying to another pattern) + + +CScrType equ apd_buf+#06 ;1 current type of screen (0=main, 1=ptn, 2=fxptn) +AlphaFlag equ apd_buf+#07 ;1 #a0 if Alpha has been pressed, else 0 + +PlayerFlag equ apd_buf+#08 ;1 0 if player is stopped, 1 if running + +COct equ apd_buf+#09 ;1 current octave +CPtn equ apd_buf+#0a ;1 current pattern + +CSRow equ apd_buf+#0b ;1 current row in ptn sequence +CSCol equ apd_buf+#0c ;1 current column in ptn sequence + +CPRow equ apd_buf+#0d ;1 current row in pattern +CPCol equ apd_buf+#0e ;1 current column in pattern + +CsrPos equ apd_buf+#0f ;1 cursor position +OldCsrPos equ apd_buf+#10 ;1 temp backup cursor position on main screen +OldCsrPos2 equ apd_buf+#11 ;1 temp backup current cursor pos (for handling vars) + +CurVal equ apd_buf+#12 ;1 current cursor bitmap value (#0f, #f0, or #ff) + +MuteState equ apd_buf+#13 ;1 mute state of channels (bit 7 = drums, bit 6 = ch3, bit 1 = ch2, bit 0 = ch1) + +InputType equ apd_buf+#14 ;1 input type (0=regular, 1=single digit, 2=double digit, 4=word) + +StateSelect equ apd_buf+#15 ;1 number of the currently selected save slot + +AutoInc equ apd_buf+#16 ;1 auto inc mode (1 = off, 0 = on) + +RowPlay equ apd_buf+#17 ;1 RowPlay mode (0 = off, #ff = on) + +PrintBuf equ ops ;6 print bitmap buffer + +;FontLUT equ 256*((HIGH(apd_buf))+1) ;font LUT + +NoteTab equ 256*((HIGH(apd_buf))+2) ;note LUT + +CsrTab equ 256*((HIGH(graph_mem))+1) ;cursor position LUT + +IF MODEL = TI83 ;fx pattern screen cursor position LUT +CsrTab2 equ graph_mem ;generated on the lowest page of graph_mem on TI83 +ENDIF +IF MODEL = TI82 || MODEL = TI8P ;generated on the lowest page of apd_buf on TI82 +CsrTab2 equ #80+(256*(HIGH(apd_buf))) +ENDIF +IF MODEL = TI8X +CsrTab2 equ 256*((HIGH(text_mem2))+1) ;generated on the second page of statram on TI83P +ENDIF + +ptntab equ 256*((HIGH(graph_mem))+2) ;pattern table + +fxptntab equ text_mem2 + +;************************************************************************************ +;actual code starts here + +begin ;initialize stuff + include "init.asm" + call waitForKeyRelease ;make sure no key is currently pressed before entering keyhandler + +mainlp ;the main loop. yes, it's very simple ;) + call keyhand + + jp mainlp + +;************************************************************************************ + + include "keyhand.asm" ;keyhandler + +;************************************************************************************ +exit ;exit HT2 + ld a,#30 ;reset mute switches (#30 = jr nc,..) + ld (mute1),a + ld (muteD),a + ld a,#9f ;#9f = sbc a,a + ld (mute2),a + ld (mute3),a + + ld a,lp_on ;switch link port lines high again + out (link),a + + +exitSP equ $+1 ;reset stack + ld sp,0 + pop ix ;restore index registers + pop iy + ei ;done automatically by CrASH + + ret ;and byebye + +;************************************************************************************ +;SUBROUTINES +;************************************************************************************ +rowPlay ;rowPlay subroutine + ld a,(PlayerFlag) ;check if player is running + or a + jp nz,_ignore ;and ignore rowPlay if that's the case + + cpl + ld (PlayerFlag),a ;set PlayerFlag to prevent double call + + call waitForKeyRelease + + xor a + ld h,a + ld d,a + ld a,(OldCsrPos) + call findCurrLineNoSeq ;find current line in sequence + + ld de,3 ;reading in backwards, therefore add 3 to offset + add hl,de + ex de,hl + + + ld bc,fxptn00 + + ld a,(CsrPos) + sub #50 + cp #f + jr c,_skipadj + sub 8 +_skipadj + add a,a + ld l,a + ld h,0 + add hl,bc + ld b,h + ld c,l + + ld a,(de) + add a,a ;a*2 + call calcPtnOffset+2 + push hl ;fx - ;stack+0 = ch1, stack+2 = ch2, stack+4 = ch3, stack+6 = fx + + ld bc,ptn00 + + ld a,(CsrPos) + sub #50 + cp #f + jr c,_skipdiv + sub 8 +_skipdiv + ld l,a + ld h,0 + add hl,bc + ld b,h + ld c,l + + call calcPtnOffset + push hl ;ch3 + + call calcPtnOffset + push hl ;ch2 + + call calcPtnOffset + push hl ;ch1 + + ld hl,_next + ld (rowplaySwap),hl + + xor a + out (kbd),a + + jp rdnotesRP ;call player +_next + pop hl ;clean stack and reset switch + pop hl + pop hl + pop hl + ld hl,rdnotes + ld (rowplaySwap),hl + xor a ;clear PlayerFlag + ld (PlayerFlag),a +_ignore + ;jp waitForKeyRelease + ret + +calcPtnOffset ;calculate offsets in note data + dec de + ld a,(de) + add a,a + ld l,a + ld h,0 + add hl,hl + add hl,hl + add hl,hl + add hl,bc + ret +;************************************************************************************ +confirmAction ;wait for confirmation/abortion of user action + ;IN: nothing | OUT: carry reset if confirmed, else abort + + ld de,#29b8 ;print CONF message + call setXY + ld de,#0c00 + call printDE + ld de,#2ab8 + call setXY + ld de,#110f + call printDE + +_rdkeys + ld a,#ef ;read key 0 + out (kbd),a + nop + nop + in a,(kbd) + rra + jp nc,_cancel ;if pressed, cancel user action + + ld a,#f7 ;read key . + out (kbd),a + nop + nop + in a,(kbd) + rra + jp nc,_confirm ;if pressed, confirm user action + jr _rdkeys ;if no key pressed, try again + +_cancel + scf ;set carry + +_confirm ;if user action confirmed, carry is already reset +_exitc +clrMsgArea ;clear message area + push af ;preserve flags + ld de,#29b2 ;delete CONF message and rest of msg area + call setXY + call clearPrintBuf + call printBuf + call printBuf + ld de,#2ab8 + call setXY + call printBuf + ld de,#2bb2 + call setXY + call printBuf + + pop af + ret + +;************************************************************************************ +calculateCopyParams ;calculate block start, length and target line # + ;IN: nothing | OUT: block start in DE, block length in BC and HL, current line # in A + exx + ld a,d ;D' holds old block start + exx + + ;ld a,(CPS) ;calculate block start in memory + ld l,a + ld h,0 + add hl,hl + add hl,hl + ex de,hl ;block start - base offset now in DE + + ;ld a,(CPE) ;calculate block length in memory + exx + ld a,e ;E' holds old block end + exx + + ld l,a + ld h,0 + add hl,hl + add hl,hl + ;xor a ;TODO: optimzed 15-08-19 - carry should never be set at this point, so we don't need to reset it + sbc hl,de + inc hl + inc hl + inc hl + inc hl ;block length now in HL + + call getCurrLineNo ;current line # now in A + + ld b,h ;block length now in BC + ld c,l + ret + + +;************************************************************************************ +getCurrLineNo ;calculate the current line number + ;IN: nothing | OUT: current line number in A | DESTROYED: C + ld a,(CsrPos) + and %11111000 + rra + rra + rra + ld c,a + ld a,(FirstLineMS) + add a,c + ret + + +;************************************************************************************ +findCurrLine ;find the current line in the sequence + ;IN: nothing | OUT: pointer to start of line in HL + xor a + ld h,a + ld d,a + + ld a,(CsrPos) + ld (OldCsrPos),a + +findCurrLineNoSeq ;entry point for finding the current row when not on seq.scr + and %11111000 ;clear lower 3 bits of cursor pos value to get to the start of the line and clear carry + rra ;divide by two + ld e,a ;store in DE + ld a,(FirstLineMS) ;read current first line + ld l,a ;store in HL + + add hl,hl ;HL*4 to get offset of first line + add hl,hl + add hl,de ;add DE to get offset of current line + ld de,ptns ;add base pointer + add hl,de ;sequence pointer now in HL + ret + +;************************************************************************************ +findNextUnused ;find next unused ptn in sequence + ;IN: first # to check in A | OUT: next unused in A, Z if no unsed patterns found + ld hl,ptns + ld bc,256*4 +_chklp + cpi ;iterate through the pattern sequence + jr z,_used ;exit loop if match found (pattern used) + cpi + jr z,_used + cpi + jr z,_used + cpi ;every 4th pattern is an fx pattern, so it's ignored + ret po ;return if pattern was unused + jr _chklp + +_used + inc a ;if pattern was used + cp #80 ;check if all patterns have been checked + ret z ;and return if that's the case + jr findNextUnused ;else, check next pattern + + +isPtnFree ;check if a pattern is free + ;IN: ptn # in A | OUT: Z if free, NZ if not free + + add a,a ;calculate offset + ld l,a ;pattern # *2 to HL + ld h,0 + add hl,hl + add hl,hl + add hl,hl + ld de,ptn00 ;add base pointer + add hl,de + + ld b,#10 + xor a + +chklp + cp (hl) ;check value + jr nz,_notfree ;exit loop if != 0 + inc hl ;else, increment pointer and check next val + djnz chklp +_notfree + ret ;return with Z set if all values have been checked + + +findNextUnusedFX ;find the next free fx pattern + ;IN: first # to check in A | OUT: next unused in A, Z if no unsed patterns found + ld hl,ptns + ld bc,256*4 +_chklp + cpi + cpi + cpi + cpi + jr z,_used + ret po + jr _chklp + +_used + inc a ;if pattern was used + cp #40 ;check if all patterns have been checked + ret z ;and return if that's the case + jr findNextUnusedFX ;else, check next pattern + +isFxPtnFree ;check if a pattern is free + ;IN: ptn # in A | OUT: Z if free, NZ if not free + + add a,a ;calculate offset + add a,a + ld l,a ;pattern # *4 to HL + ld h,0 + add hl,hl + add hl,hl + add hl,hl + ld de,fxptn00 ;add base pointer + add hl,de + + ld b,#20 + jr chklp-1 + +;************************************************************************************ +errorHand ;error handler + ;IN: A - error code + ld d,#0e + ld e,a + +printMsg ;print a message to the message area + ;IN: DE - message + push de + + ex af,af' + ld de,#29b2 + call setXY + ex af,af' + + pop de + + jp printDE + + +;************************************************************************************ +printMute12 ;print Mute state ch1/2 + ld de,#2a88 + call setXY + + ld de,#0102 + ld a,(MuteState) + rra + jr nc,_skip + ld d,#16 +_skip + rra + jr nc,_skip2 + ld e,#16 +_skip2 + ;call printDE + ;ret + jp printDE + + +printMute3D ;print Mute state ch3/4 + ld de,#2b88 + call setXY + + ld de,#030D + ld a,(MuteState) + rla + jr nc,_skip + ld e,#16 +_skip + rla + jr nc,_skip2 + ld d,#16 +_skip2 + ;call printDE + ;ret + jp printDE + +;************************************************************************************ +initSeqCsr + ;xor a ;reset cursor pos + ld a,(OldCsrPos) + ld (CsrPos),a + +printCsr ;print the cursor + ld hl,CsrTab ;load pointer to CsrPos LUT + +csrTypeSwap equ $+1 + ld c,#0f ;cursor bitmask + ld a,(CsrPos) + add a,a ;A=A*2 + add a,l + ld l,a + ld a,(hl) + or a + jp p,_skip ;if bit 7 is set + ld c,#f0 ;change bitmask to #f0 + and %01111111 ;clear bit 7 +_skip + ld d,a + inc l + ld e,(hl) + call setXY + +IF MODEL = TI82 + ;nop + ;nop + ;nop + ;nop + ld a,(hl) ;TODO: optimized timewaster, needs testing + ld a,(hl) +ELSE + call lcdWait3 +ENDIF + ld a,c + out (lcd_data),a + ret + +printCsr2 ;alternative table pointer for FX screen + ld hl,CsrTab2 + jr printCsr+3 + +delCsr2 ;alternative table pointer for FX screen + ld hl,CsrTab2 + jr delCsr+3 + +delCsr ;delete the cursor + ld hl,CsrTab ;load pointer to CsrPos LUT + ld a,(CsrPos) + add a,a ;A=A*2 + add a,l + ld l,a + ld a,(hl) + and %01111111 ;clear bit 7 + ld d,a + inc l + ld e,(hl) + call setXY + +IF MODEL = TI82 + ;nop + ;nop + ;nop + ;nop + ld a,(hl) + ld a,(hl) +ELSE + call lcdWait3 +ENDIF + xor a + out (lcd_data),a + ret + +;************************************************************************************ +divNoteVal ;split note value into octave and val w/in the octave + ;IN: note val in A | OUT: octave in B, note val in C + + ld b,#ff + dec a ;0=silence, so lowest actual note val is 1 -> decrement by 1 +_divlp ;effectively dividing A by 12 + inc b ;increment octave + ld c,a ;preserve remainder + sub 12 ;subtract 12 + jr nc,_divlp ;loop until result was <0 + + ret + +;************************************************************************************ +printFxScr ;print an FX pattern screen + + call clrMsgArea ;clear message area + + ld a,LOW(kjumptab)+16 ;set dirkey jump table pointer offset + ld (kdirswitch),a + + ld a,(CsrPos) ;preserve cursor pos on seq.scr + ld (OldCsrPos),a + + ld a,2 ;set current screen type + ld (CScrType),a + + call printSingleLN + +_header ;printing ptn#/curr. octave info + ld de,#2182 + call setXY + + ld de,#1214 ;PT(N) + call printDE + + ld de,#2382 + call setXY + + call getSeqOffset ;find pattern# + + ld a,(CPtn) ;load current ptn# + cp #40 ;if it's invalid (> #3f) + jp nc,printSeqScr ;default to sequence screen + +printFxScrNoInit ;init point when cycling through patterns + + call printChars ;print ptn# + + ld de,#218e + call setXY + + ld a,(CPtn) + ld hl,fxptntab + call findCurrFxPtn ;get the pattern pointer + + push de ;preserve pointer for printing fx params later + + ex de,hl + + call printFXP + + ld de,#258e + call setXY + + call printFXP + + ld de,#228e + call setXY + + pop hl + inc hl + + call printFXP + + ld de,#268e + call setXY + + call printFXP + + xor a ;reset cursor pos + ld (CsrPos),a + call printCsr2 ;initialize cursor + + call waitForKeyRelease + jp keyhand + +printFXP ;print FX params + ld b,8 +_lp + ld a,(hl) + inc hl + inc hl + push hl + push bc + call printCharsNoFF + pop bc + pop hl + djnz _lp + + ret + + +;************************************************************************************ +findCurrPtn ;locate the currently selected pattern in memory + ;IN: nothing | OUT: pattern pointer in DE + + ld a,(CPtn) ;read current ptn# TODO: optimize by moving this to after the findCurrFxPtn label + +findPtn ;find ptn in memory + ld hl,ptntab ;10 ;point to pattern position LUT + +findCurrFxPtn ;entry point for finding fx pattern. A and HL need to be preset + + add a,a ;4 ;A=A*2 + add a,l ;4 + ld l,a ;4 + jr nc,_skip1 ;12/7 + inc h ;4 +_skip1 ;ptn pointer now at (HL) + + ld e,(hl) + inc hl + ld d,(hl) ;ptn pointer now in DE + ret + +;************************************************************************************ +getSeqOffset ;get offset in ptn sequence based on current cursor pos on seq.screen + ;IN: nothing | OUT: sequence pointer in HL, [current] ptn# in A,(CPtn) | destroyed: DE + + xor a ;clear carry + ld h,a ;ld h,0 + ld d,a + ld a,(CsrPos) ;read old cursor position (from seq.scr) + rra ;divide by 2 + ld e,a + ld a,(FirstLineMS) ;check first line on seq scr + ld l,a + add hl,hl ;offset*4 + add hl,hl + add hl,de ;+ position offset = total offset in ptn sequence + ld de,ptns ;add ptn sequence base + add hl,de ;seq.pointer now in HL + + ld a,(hl) ;load ptn# into A + ld (CPtn),a ;store it in (CPtn) + ret + +;************************************************************************************ + + +printPtnScr ;print a pattern screen + + call clrMsgArea ;clear message area + + ld a,LOW(kjumptab)+8 ;set dirkey jump table pointer offset + ld (kdirswitch),a + + ld a,1 ;set current screen type + ld (CScrType),a + + ld a,(CsrPos) + ld (OldCsrPos),a + + call printSingleLN + +_header ;printing ptn#/curr. octave info + ld de,#2182 + call setXY + + ld de,#1214 ;PT(N) + call printDE + + ld de,#000c ;OC(T) + call printDE + + ld de,#2382 + call setXY + + call getSeqOffset + + ld a,(CPtn) ;current ptn# + cp #7f ;if pattern# > #7f + jp nc,printSeqScr ;default to sequence screen + +printPtnScrNoInit ;init point when cycling through patterns + + call printChars + + ld a,(COct) ;current octave + call printCharL + +printPtnScrBasic ;init point when not reprinting ptn nr, octave etc. + ld de,#218e + call setXY + + + call findCurrPtn + + push de ;preserve pointer for printing octave #s later + + call printNoteNames + ex de,hl + ld de,#258e + call setXY + + ex de,hl + call printNoteNames + + ld de,#228e + call setXY + + pop de ;retrieve pattern pointer + + call printOctaves + + push de + ld de,#268e + call setXY + + pop de + call printOctaves + + ld a,#50 ;init cursor pos + ld (CsrPos),a + + ld a,#ff ;init cursor type + ld (csrTypeSwap),a + + call printCsr + + call waitForKeyRelease + jp keyhand + + +printOctaves + ld b,8 +_lp + ld a,(de) ;read note byte + inc de ;point to next byte + push de ;preserve pattern pointer + push bc ;preserve counter + or a + jr nz,_skip2 ;if note val = 0 + ld a,#16 ;print a dash + jr _skip3 +_skip2 + call divNoteVal ;octave val returned in B + + ld a,b ;get it into A +_skip3 + ex af,af' + call clearPrintBuf + ex af,af' + call printCharLNC ;and print it + + pop bc + pop de + djnz _lp + ret + + + + +printNoteNames + ld b,8 +_lp + ld a,(de) ;read note byte + inc de + push de + push bc + or a + jr nz,_skip2 ;if note val = 0 + ld d,#16 ;load dashes into DE + ld e,d + jr _skip3 +_skip2 + call divNoteVal ;note val returned in C + + ld a,c ;find note name + ld hl,notenames ;point to note name LUT + add a,a ;A=A*2 + ld e,a + ld d,0 + add hl,de ;add offset to LUT pointer + + ld d,(hl) ;get string into DE + inc hl + ld e,(hl) + +_skip3 + call printDE ;and print it + + pop bc + pop de + djnz _lp + ret + + + + +printSingleLN ;print single digit line numbers + + ld de,#208e + call setXY + + xor a ;starting with line 0 + ld b,8 + + call printSingleLP ;print the first column + + ld de,#248e + call setXY + + ld a,8 ;starting with 8, print 2nd column + ld b,a + call printSingleLP + + ret + +printSingleLP ;print loop for printing single digit line #s + push af + push bc + call printCharL + pop bc + pop af + inc a + djnz printSingleLP + ret + +;************************************************************************************ +printSeqScr ;print the sequence (main) screen + ;call clrMsgArea ;clear message area + + ld a,LOW(kjumptab) ;reset dirkey jump table pointer offset + ld (kdirswitch),a + + xor a + ld (CScrType),a ;set current screen type + ld (InputType),a ;reset input type + + ld a,#0f ;init cursor type + ld (csrTypeSwap),a + +printSeqScr0 +printLineNumbers ;print line numbers on main screen + ld de,#2082 + call setXY + + ld b,10 ;10 lines to print + ld a,(FirstLineMS) ;load first line number + +_plnlp + push af + push bc + call printCharsNoFF + pop bc + pop af + inc a + djnz _plnlp + +printPtnSequence + ld de,#2182 ;ch1 + call setXY + + ld hl,ptns ;point HL to start of ptn sequence + ld a,(FirstLineMS) ;get first row to be printed + ld e,a ;load into DE + ld d,0 + add hl,de ;first row * 4 = offset in ptn sequence + add hl,de + add hl,de + add hl,de + + ld c,10 ;printing 10 rows for each column + call printSeqColR ;print upper nibbles + ld de,#2282 + call setXY + call printSeqColL ;print lower nibbles + + ld de,#2382 ;ch2 + call setXY + + inc hl ;increment to point to next channel + push hl ;preserve seq. pointer (printSeqCol doesn't do this for speed reasons) + call printSeqCol + + ld de,#2482 ;ch3 + call setXY + pop hl + + inc hl + call printSeqColR + ld de,#2582 ;ch2 + call setXY + call printSeqColL + + ld de,#2682 ;fx-ch + call setXY + + inc hl + call printSeqCol + + ld a,(OldCsrPos) + ld (CsrPos),a + + ret + +;************************************************************************************ +printSeqColR ;print one right half-column of pattern sequence + push hl ;preserve seq. pointer + ld b,c ;printing 10 rows for each column +_ppslp + push hl ;preserve sequence pointer + push bc ;preserve counter + ld a,(hl) ;load byte to print + call printCharR ;print upper nibble, right-aligned + pop bc ;retrieve counter + pop hl ;retrieve seq. pointer + ld de,4 ;increment seq. pointer (by 4, because each row of the sequence is 4 bytes long) + add hl,de + djnz _ppslp ;loop until 10 rows have been printed + pop hl ;retrieve seq. pointer + ret + + +printSeqColL ;print one left half-column of pattern sequence + push hl + ld b,c +_ppslp + push hl + push bc + ld a,(hl) + call printCharL + pop bc + pop hl + ld de,4 + add hl,de + djnz _ppslp + pop hl + ret + + +printSeqCol ;print one full column of pattern sequence + ld b,c +_ppslp + push hl + push bc + ld a,(hl) + call printChars + pop bc + pop hl + ld de,4 + add hl,de + djnz _ppslp + ret + +;************************************************************************************ +printCharR + ex af,af' ;preserve byte to be printed + call clearPrintBuf ;clear print buffer + ex af,af' ;retrieve byte to be printed + call hex2charU ;convert upper nibble + ld c,1 ;init registers for setting up the print buffer (c=number of digits to print, b'=#83 signals shifted char) + exx + ld b,#8a + call setupPB1char ;setup print buffer + jr printBuf ;and finally print what's in the buffer + + +printCharL + ex af,af' + call clearPrintBuf + ex af,af' + call hex2charL +printCharLNC + ld c,1 + exx + ld b,0 + call setupPB1char + jr printBuf + + + +printCharsNoFF + call hex2charNoFF + jr printCharsNoConvert + +printChars ;print the 2 characters in (CharString) + call hex2char ;convert to chars + +printCharsNoConvert ;print (CharString) without converting ASCII first + ld de,(CharString) ;load chars into DE + +printDE ;printing with custom value in DE + call setupPrintBuf ;convert to bitmap + +printBuf + ld hl,PrintBuf ;print a pair of characters + ld b,6 + ;call drawlp2 + ;ret + jp drawlp2 + +;************************************************************************************ +clearPrintBuf ;clear the print buffer in (ops) + xor a + ld hl,ops + ld b,5 +cpblp + ld (hl),a + inc l + djnz cpblp + ret + +;************************************************************************************ +setupPrintBuf ;set up print buffer with 5-byte bitmap (2 chars) + ;INPUT: left char in d, right char in e + + call clearPrintBuf ;clear the print buffer + + ld a,d ;load first (left) char + ld c,2 ;printing 2 characters + exx + ld b,0 + +setupPB1char ;init point for printing 1 char + ;char in A, B' = 0 (left) or #83 (right), C=1, print buffer must be cleared manually + + ld d,1 + (HIGH(apd_buf)) ;point to font bitmaps +_spblp + ld hl,ops ;print buffer resides in (ops) + + ld c,a ;multiply character byte * 5 + add a,a + add a,a + add a,c + add a,b ;and add right side offset as required + ld e,a + ld b,5 +_getbitslp ;get 5 byte-length bitmaps + ld a,(de) + or (hl) ;and or them into the print buffer + ld (hl),a + inc e + inc l ;inc hl + djnz _getbitslp + + exx + dec c ;check if all chars have been set up + ret z ;and return if yes + + ld a,e ;otherwise, get second char + exx + ld b,#8a ;prep b with offset for shifted chars + jr nz,_spblp ;JR NZ??? It's always NZ at this point. + +;************************************************************************************ +clrS ;clear main screen area + ld d,#1f ;select horiz. pos + ld c,7 ;clearing 7 columns +_clrlp + inc d + ld e,#82 + call setXY ;TODO: does not work with setXY2 + + xor a + ld b,#3b ;clearing #3b rows + call drawLoop + + dec c + jr nz,_clrlp + ret + + +;************************************************************************************ +drawLoop ;simple draw loop (used for screen initialization) + out (lcd_data),a + call lcdWait3 + djnz drawLoop + ret + +drawlp2 ;little more complex draw loop + ld a,(hl) + inc hl + out (lcd_data),a +IF MODEL = TI82 + push hl ;waste some time + pop hl +ELSE + call lcdWait3 +ENDIF + djnz drawlp2 + ret + +;************************************************************************************ +lcdWait2 ;waste some time till LCD controller can receive next command + jr lcdWait3 ;12t +lcdWait3 + +IF MODEL != TI82 ;lcdWait for slow display drivers +; _lp + ex (sp),hl + ex (sp),hl + ex (sp),hl + ex (sp),hl + ex (sp),hl + ex (sp),hl + ex (sp),hl + ex (sp),hl ;152 +ENDIF + ret + +;************************************************************************************ +setXY ;set print position on screen + ;input: D=horiz.pos, E=vert.pos | out: A destroyed + ld a,d ;set horizontal pos + out (lcd_crt),a + call lcdWait2 + + ld a,e ;set vertical pos + out (lcd_crt),a + +setXYmod equ $+1 + jr lcdWait2 ;exit via lcdWait2 - SELF-MODIFYING: swapped with a jr to lcdWait3 after initSCR + + +;************************************************************************************ +waitForKeyRelease ;wait for key release function. TODO: how about skip the out command? It should not be necessary... + +_rdkeys + in a,(kbd) + cpl ;4 ;would be nice to skip these two lines + or a ;4 ;but somehow that doesn't work + jr nz,_rdkeys + +_wait + ld b,a +_waitlp + ex (sp),hl + ex (sp),hl + djnz _waitlp + + ret ;5 + +;************************************************************************************ +hex2char ;convert hex value to character string (using custom font) + ;input: A=hex byte | output: string in (charstring), A destroyed + + cp #ff ;check if we have an #ff byte + jr z,hex2charFF + +hex2charNoFF + push af ;preserve input byte + and %00001111 ;extract lower nibble + ld (CharString),a ;save it + pop af ;retrieve input byte + rra ;shift right x4 and clear bit 4-7 to extract upper nibble + rra + rra + rra + and %00001111 + ld (CharString+1),a + ret + +hex2charFF + ld a,#16 ;replace #ff with -- + ld (CharString),a + ld (CharString+1),a + ret + + +hex2charU ;convert upper nibble of hex value to right-aligned char and return it in A + cp #ff + jr z,hex2FF + rra ;shift right x4 and clear bit 4-7 to extract upper nibble + rra + rra + rra + and %00001111 + ret + +hex2charL ;convert lower nibble of hex value to left-aligned char and return it in A + cp #ff + jr z,hex2FF + and %00001111 + ret + +hex2FF ;replace hex digit with - (dash) + ld a,#16 + ret + + include "mem.asm" + +;************************************************************************************ +;TABLES AND INCLUDES +;************************************************************************************ + +baseCounterLUT ;counter values for octave 6, all other counter values are derived from this + + ;dw #4000, #43CE, #47D6, #4C1C, #50A3, #556E, #5A83, #5FE4, #6598, #6BA3, #7209, #78D1 + dw #2000, #21E7, #23EB, #260E, #2851, #2AB7, #2D41, #2FF2, #32CC, #35D1, #3905, #3C68 + +font + include "font3.asm" + +htlogo ;the HT2 logo + db %11110101 + db %11110001 + db %11110101 + db %11111111 + db %11111111 + + db %00010011 + db %10111101 + db %10111011 + db %11110001 + db %11111111 + +varmsgs ;global var names (right side of screen) + + db #10,#12 ;LP + db #13,#12 ;SP(D) + db #b,#13 ;CS + db #b,#e ;CE + +notenames + db #c,#16 ;c + db #c,#15 ;c# + db #d,#16 ;d + db #d,#15 ;d# + db #e,#16 ;e + db #f,#16 ;f + db #f,#15 ;f# + db #17,#16 ;g + db #17,#15 ;g# + db #0a,#16 ;a + db #0a,#15 ;a# + db #0b,#16 ;b + + + +;IF MODEL = TI83 + ;org 256*(1+(HIGH($))) ;align to next page +;ENDIF +IF ((HIGH($))<(HIGH($+30))) + org 256*(1+(HIGH($))) ;align to next page if necessary +.WARNING kjumptab or notevals crosses page boundary, realigned to next page +ENDIF + +kjumptab ;jump table for keyhandler. MAY NOT CROSS PAGE BOUNDARY! + dw kdown + dw kleft + dw kright + dw kup + dw kpdown + dw kpleft + dw kpright + dw kpup + dw kfdown + dw kfleft + dw kfright + dw kfup +ktest equ $-1 +; IF ((HIGH(kjumptab))<(HIGH(ktest))) +; .ERROR kjumptab crosses page boundary +; ENDIF + +notevals equ $-#a ;LUT for note name -> val conversion + db 10 ;A + db 12 ;B + db 1 ;C + db 3 ;D + db 5 ;E + db 6 ;F + db 8 ;G +ttest equ $-1 +;IF ((HIGH(notevals))<(HIGH(ttest))) +;.ERROR notevals crosses page boundary +;ENDIF + +;************************************************************************************* +;music player, work area, savestates + +mplay + include "16bitplayer.asm" + +savestateLUT ;32 byte save state lookup table + dw savestates ;DEBUG + dw firstend-1 ;DEBUG + ds 28 + +savestates ;compressed savestates + include "cpmusic.asm" + +firstend equ $ ;DEBUG +;************************************************************************************* +;memend equ $+2 + org mem_end-2 +version + db 0,1 ;savestate format version + + +IF ((MODEL != TI82)) ; && (MODEL != TI8P)) + dw #0000 +ENDIF diff --git a/mem.asm b/mem.asm new file mode 100644 index 0000000..7b0ad7f --- /dev/null +++ b/mem.asm @@ -0,0 +1,649 @@ +;memory related subroutines +;************************************************************************************ +stateSelect ;prompt user to select a savestate (slot) number + ld a,(CScrType) + cp 2 + + call z,delCsr2 + jr _skip + call delCsr +_skip + jp inputSlotNr + +;************************************************************************************ +delSlot ;delete a save slot + + ld de,#0d13 ;print "DS" message + call printMsg + call stateSelect + call confirmAction + ret c + +delSlotNoConfirm ;delete slot without asking for confirmation + ld a,(StateSelect) ;read save slot number + add a,a ;calculate offset in savestate LUT + add a,a + ld e,a + ld d,0 + ld hl,savestateLUT ;calculate pointer to LUT entry + add hl,de + + ld e,(hl) ;load lo byte of delslot.start + inc hl + ld a,(hl) ;check if savestate is empty + or a + ret z ;and exit if that's the case + + ld d,a ;delslot.start now in DE + + dec hl ;preserve LUT pointer on stack + push hl + inc hl + + inc hl + ld c,(hl) + inc hl + ld b,(hl) + inc bc ;delslot.end+1 now in BC + push bc + + xor a + ld hl,mem_end-3 + sbc hl,bc + + ld b,h + ld c,l ;remaining block length now in BC + pop hl ;delslot.end+1 in in HL + + push de + push hl + + ldir ;copy remaining block to new location + +delUpdateLUT + pop hl + dec hl ;delslot.end + pop de ;delslot.start + + xor a + sbc hl,de ;delslot.length now in HL + + pop bc ;retrieve LUT pointer + ld (bc),a ;clear LUT entry + inc bc + ld (bc),a + inc bc + ld (bc),a + inc bc + ld (bc),a + + ld (_oldSP),sp ;preserve stack pointer + ld sp,hl ;delslot.length now in SP + ld hl,savestateLUT + ld b,d ;delslot.start now in BC + ld c,e + exx + ld b,#10 ;updating 16 word-length entries (8 long) + +_lp + exx + ld e,(hl) ;read entry from savestate LUT + inc hl + ld d,(hl) + + ex de,hl + xor a + sbc hl,bc ;check if entry < delslot.start (or entry == 0) + ex de,hl + + jr c,_noupdate ;if so, move on to the next entry + + ex de,hl + add hl,bc ;restore slot val + sbc hl,sp ;subtract delslot.length from entry + ex de,hl + + dec de + ld (hl),d ;store updated slot val in LUT + dec hl + ld (hl),e + inc hl + +_noupdate + inc hl + exx + djnz _lp + +_oldSP equ $+1 ;restore stack pointer + ld sp,0 + + ;jp waitForKeyRelease + ret + +;************************************************************************************ +zap ;delete song currently loaded in work area + ld hl,#10 ;clear speed, usr drum, lp + ld (musicData),hl + ld l,0 + ld (musicData+2),hl + + ld hl,musicData+4 ;clearing sequence (writing 1025 #ff bytes) + ld de,musicData+5 + ;ld bc,1024 + ld bc,1025 ;NEW + ld a,#ff + ld (hl),a + ldir + + xor a ;clearing pattern area (writing 4096 #00 bytes) + ld (hl),a + ld bc,4095 + ldir + + ret + +;************************************************************************************ +addressCompare ;compare two 16-bit values + ;IN: val 1 in DE, val 2 in BC | OUT: higher val in BC + + ex af,af' + inc a ;signal to save code that a savestate has been found + ex af,af' + + ;dec hl + ld e,(hl) + inc de + push hl + + ld h,b + ld l,c + + xor a ;clear carry (should in theory be cleared by previous or d) + sbc hl,de + jr nc,_return ;if BC > DE, all is good + + ld b,d ;else, DE -> BC + ld c,e + +_return + pop hl + ;inc hl ;pointer adjustment + ret + +;************************************************************************************ +save ;save a compressed backup savestate of the current song + + call delSlotNoConfirm ;if savestate exists in the current slot, delete it + +_findMemLoc ;iterate through savestate LUT to find the next free memory location + ld hl,savestateLUT+31 + ld bc,0 + + xor a + ex af,af' + ;xor a + exx + ld b,8 + + +_findlp + xor a + exx + ld d,(hl) ;read hi byte of slot.end + or d ;if it's non-zero, this is an existing savestate + dec hl + + call nz,addressCompare + + dec hl ;else, decrement pointer + dec hl + dec hl + exx + djnz _findlp ;and loop + + exx + ld de,savestates ;if no existing save states are found, set MemLoc to start of savestate area + + ex af,af' + or a ;A' holds # of savestates found TODO BUG: A=0 even though it shouldn't be, likewise BC=0 + jr z,_proceed + + ld d,b + ld e,c + +_proceed + ld a,(StateSelect) ;read selected state # + add a,a + add a,a + ld c,a + ld b,0 + ld hl,savestateLUT + add hl,bc ;point to it in LUT + ld (hl),e ;and write start address of the slot to be saved to LUT + inc hl + ld (hl),d + + inc hl + ld (LUTpointer),hl ;preserve pointer address for writing slot.end value later on + +;****** + ;ld de,savestates ;DEBUG + ;DE holds start address (target) + ld hl,musicData + ld bc,#04ff ;b=counter, c=bogus high value to obfuscate decrement by ldi + +_savevars + ldi ;save global vars + call chkMemEnd ;test for out of mem error + djnz _savevars + +_saveseq ;save song sequence + ld a,(hl) + ldi ;save 1 byte + call chkMemEnd ;test for out of mem error + inc a ;check if last saved byte was #ff + jr nz,_saveseq ;save next byte if it wasn't + +_saveptns + ex de,hl ;now HL = store pointer + ld de,ptn00 ;DE = read pointer + +_saveptnlp + call chkLastPtn ;check if all ptns have been saved + jr nz,_skip1 + ld a,#ff ;if yes, write an #ff byte + ld (hl),a + inc hl ;update pointers + jr saveFX ;and continue with fx ptns + +_skip1 + ld a,#df ;assume that the following n patterns are empty + ld (hl),a ;write #df byte + ld c,#1f ;C = # of patterns to check, checking the following #20 patterns + +_isPtnEmpty ;check if current pattern is empty + ld b,#10 ;check #10 rows + push de +_lp + ld a,(de) ;check if byte == 0 + or a + jr nz,_isRowEmpty ;if it isn't, continue with checking for empty rows + inc de ;else, inc pointer + djnz _lp ;and check next row + + pop de ;retrieve load pointer + inc (hl) ;increment "empty ptns" counter - DOESN'T THIS HAVE TO BE inc (hl)??? (was inc hl) + ;ATTN: SURE? + + push hl ;increment load pointer by #10 + ld hl,#10 + add hl,de + ex de,hl + pop hl + + dec c ;decrement "# of ptns to check" counter + jr nz,_isPtnEmpty ;and check next ptn if done with all #20 ptns + + inc hl ;else, increment store pointer + ex de,hl + call chkMemEnd ;check for mem_end + ex de,hl + jr _saveptnlp ;and move on to the next ptn + + +_isRowEmpty + pop de ;retrieve load pointer + + ld a,(hl) ;NEW: check if e0 byte was previously written + cp #e0 ;NEW: + jr c,_skipxx ;NEW: + inc hl ;NEW: and inc save pointer if necessary + +_skipxx + ld a,#cf ;assume next row is empty + ld (hl),a + ld b,#10 ;check up to #10 rows +_lp2 + ld a,(de) ;check if byte == 0 + or a + jr nz,_rNotEmpty ;if byte != 0, row isn't empty + + inc (hl) ;else, increment "empty rows" counter + inc de ;increment load pointer + +_exitlp + djnz _lp2 ;and keep checking for empty rows if not all have been checked yet + + ld a,#cf ;NEW 20-09: unless end of pattern reached with non-empty row, inc write pointer + cp (hl) + jr z,_skipxxx + inc hl +_skipxxx + jr _saveptnlp ;else, move on to the next ptn + +_rNotEmpty + ld a,(hl) ;if row wasn't empty + cp #d0 ;check if an "empty rows" or "empty ptns" counter was previously written + jr c,_skipx + inc hl ;increment store pointer if yes +_skipx + ex de,hl + ldi ;copy 1 byte + call chkMemEnd ;check for mem_end + inc bc ;adjust counter + ex de,hl + ld a,#cf ;assume next row is empty + ld (hl),a + jr _exitlp ;and move on to the next row + + +saveFX ;compress and save the fx patterns + ld de,fxptn00 + ex de,hl ;now DE = store pointer and HL = read pointer again + + push hl ;check if all fx ptns are empty. + ld bc,#800 ;check following 2048 bytes + +_clp + ld a,(hl) + or a + jr nz,_cont + inc hl + dec bc + ld a,b + or c + jr nz,_clp + + pop hl ;If all fx ptns were empty, write #ff byte and exit. + cpl + ld (de),a + jp _success+1 + +_cont + pop hl + ex af,af' + ld a,#ff ;AF' = pattern counter + ex af,af' + +_sfxlp + ex af,af' + inc a ;inc pattern counter + cp #3f ;SHOULD BE cp #40? if it's #40 or bit 7 is set, we're done saving + ;ret nc + jp nc,_success + ex af,af' + +_lookAhead ;check if the next ptn is empty (next 32B == 0) + ld b,#20 + push hl ;preserve read pointer +_lAlp + ld a,(hl) ;check if bytes == 0 + or a + inc hl + jr nz,_fxNotEmpty ;if byte != 0, pattern isn't empty + djnz _lAlp + + pop hl ;if pattern was empty, retrieve read pointer + ld bc,#20 ;point to next pattern (add 32) + add hl,bc + jr _sfxlp ;repeat from start + +_fxNotEmpty + pop hl + push hl + ld bc,#20 + add hl,bc +_fxNElp + ld a,(hl) ;check if remaining fx ptns (except the current one) are empty + or a + inc hl + jr nz,_writeFxPtn ;if byte != 0 found, copy ptn normally + + ld a,h ;check if end of work area reached + cp HIGH(musicEnd) + jr nz,_fxNElp + ld a,l + cp LOW(musicEnd) + jr nz,_fxNElp ;if not, keep parsing fx ptns + + ex af,af' ;if all remaining fx ptns were empty + add a,#80 ;set bit 7 of the ptn counter + ex af,af' + +_writeFxPtn + ex af,af' + ld (de),a ;write ptn # at store pointer + ex af,af' + pop hl ;retrieve load pointer + inc de + ;ld bc,#20 ;copying 32 bytes + ld b,#20 +_writelp + ldi ;transfer a byte + call chkMemEnd ;check for mem_end + ;ldi + ;jr nz,_writelp + djnz _writelp + jr _sfxlp ;and on to the next pattern + +_success + dec de + ;ld a,(StateSelect) +LUTpointer equ $+2 + ld (savestateLUT+2),de ;write end address to savestate LUT + xor a + jp errorHand +;************************************************************************************ +chkLastPtn ;check if all used note patterns have been saved + ;OUT: Z if all used ptns have been saved, else NZ + push de +_lp + ld a,d ;check if end of note ptn area reached + cp HIGH(fxptn00) + jr nz,_skip + ld a,e + cp LOW(fxptn00) + jr z,_skip2 +_skip + ld a,(de) ;check if byte is empty + or a + inc de + jr z,_lp ;if it is, check next byte + +_skip2 ;else return + pop de + ret + ;jp waitForKeyRelease ;not needed since kDot is ignored when returning +;************************************************************************************ + +chkMemEnd ;check if end of usr memory reached + ;IN: nothing | OUT: jumps to errorHand if mem_end reached + or a ;clear carry + push hl + ld hl,mem_end-4 + sbc hl,de ;subtract current mempos from mem_end-3 + pop hl + ret nc + +saveError ;handling out of memory errors + pop hl ;pop useless return address + ld a,2 ;set error code + jp errorHand + +;************************************************************************************ +load ;load a song from a backup savestate. + ;IN: # of savestate to load in (StateSelect) | OUT: nothing, AF,BC,DE,HL destroyed. + call zap ;clear work area + + ld a,(version) ;check savestate format version + or a + jr z,_ldstart + ld a,6 ;if version != 0, abort loading and generate error + jp errorHand + +_ldstart +; ld hl,ptns ;initialize sequence with #ff bytes ;this is all unnecessary since we zap before +; ld de,ptns+1 +; ld bc,1025 +; ld a,#ff +; ld (hl),a +; ldir +; +; xor a ;initialize rest of work area with #00 +; ld (hl),a +; ld bc,16*256 +; ldir + + ld hl,savestateLUT ;set pointer to savestate LUT + ld a,(StateSelect) ;calculate offset + add a,a + add a,a ;NEW: each LUT entry is now 4 bytes + ld e,a + ld d,0 + add hl,de ;add it to LUT pointer + ld e,(hl) ;get address of savestate to load in DE + inc hl + ld a,(hl) + or a ;trap empty savestates + ld a,5 + jp z,errorHand ;abort and ouput error if empty savestate encountered + ld d,(hl) + ex de,hl ;move it to HL + ld de,musicData ;set destination address + +_ldvars ;load global song vars + ldi ;speed + ldi ;usr drum pointer + ldi + ldi ;loop point + +_ldseq ;load sequence + ld a,(hl) ;check for seq. end marker (#ff) + cp #ff + jr z,_ldptns ;continue with loading patterns if end marker found + ldi ;else, move byte from savestate to work area + jr _ldseq + +_ldptns + inc hl ;adjust pointer to savestate + ld de,ptn00 ;adjust pointer to work area + +_ldptnlp + ld a,(hl) ;get a byte from savestate + cp #ff ;check for ptn area end marker (#ff) + jr z,_ldfxptns ;if end marker is found, continue with loading fx patterns + + push hl ;preserve pointer to savestate + ld h,0 ;init offset value + + cp #e0 ;check if byte >= #e0 ("empty patterns") + jr c,_skip1 + sub #df ;offset = ([hl] - #df)*16 + ld l,a + add hl,hl + add hl,hl + add hl,hl + add hl,hl + jr _skip3 + +_skip1 + cp #d0 ;check if byte >= #d0 ("empty rows") + jr c,_noCP ;if it isn't, we have normal uncompressed data + sub #cf ;else, offset = [hl] - #cf + ld l,a + +_skip3 + add hl,de ;add offset to work area pointer + ex de,hl + pop hl ;restore savestate pointer + inc hl ;increment savestate pointer + jr _ldptnlp ;read next byte + +_noCP + pop hl ;restore savestate pointer + ldi ;transfer byte to work area and increment pointers + jr _ldptnlp ;read next byte + + +_ldfxptns +ldfxpnts + inc hl ;adjust pointer to savestate + ;ld de,fxptn00 ;adjust pointer to work area + +_ldfxptnlp + ld de,fxptn00 ;adjust pointer to work area + ld a,(hl) ;load ptn # + + cp #ff ;if ptn# == #ff, there are no fx patterns to load + ret z + + push af + ;and #7f + and #3f ;mask out bit 6,7 + + inc hl + push hl + + ld h,0 + + add a,a + add a,a + + ld l,a ;patnum is max #3f, so can add a,a twice before loading into hl + + ;add hl,hl ;offset = ptn# * 32 + ;add hl,hl + add hl,hl + add hl,hl + add hl,hl + + add hl,de ;add offset to work area pointer + ex de,hl + + pop hl + + ld bc,32 ;copy 32 bytes + ldir + + pop af + ;rla ;check if bit 7 of ptn# was set + cp #3f ;check if bit 7 of ptn# was set or ptn# was >#3f + ;jr nc,_ldfxptnlp ;???read next ptn if it wasn't + jr c,_ldfxptnlp ;TEST DEBUG + ret ;else we're done. +;************************************************************************************ +; +; ; isFxPtnFree +; ; ld b,#20 +; ; ld hl,fxptntab +; ; jr isPtnFree +; +; isNotePtnFree ;determine if a pattern is unused +; ;IN: A = ptn # | OUT: Z if ptn is empty; AF,BC,DE,HL,BC' destroyed +; ld b,#10 +; isPtnFree +; push de +; push hl +; push bc +; +; call findPtn ;ptn pointer now in DE +; ld hl,0 +; ld b,0 +; exx +; pop bc +; +; _lp +; exx +; ld a,(de) +; ld c,a +; add hl,bc +; exx +; djnz _lp +; +; exx +; ld a,h +; or l ;set flags +; pop hl +; pop de +; ret +; ;************************************************************************************ \ No newline at end of file diff --git a/music.asm b/music.asm new file mode 100644 index 0000000..b60f537 --- /dev/null +++ b/music.asm @@ -0,0 +1,21 @@ +;an empty song, for initialization + +speed + db #10 ;speed +usrDrum + dw #0 ;usr drum pointer +looprow + db 0 ;loop point (row#) + +ptns ;the pattern matrix + ds 256*4,#ff ;1024+1 #ff bytes + ;db 1,#ff ;shouldn't this be just #ff? + db #ff + +ptn00 ;the note patterns + ds 16*128 ;128*16 #00 bytes + +fxptn00 ;the fx patterns + ds 32*64 ;64*32 #00 bytes + +musicEnd equ $ ;=savestate LUT \ No newline at end of file diff --git a/oysterpac.pl b/oysterpac.pl new file mode 100755 index 0000000..8a145d2 --- /dev/null +++ b/oysterpac.pl @@ -0,0 +1,128 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Fcntl qw(:seek); + +print "oysterpac 0.1 - TI program variable packer by utz\n"; + +my $debuglvl = $#ARGV + 1; + +if ($debuglvl != 2) { + print "syntax: oysterpac.pl \n"; + exit 1; +} + +my $infile = $ARGV[0]; +my $outfile = $ARGV[1]; +my $target = substr $ARGV[1], -3; + +if ($target ne '82p' && $target ne '83p' && $target ne '8xp' && $target ne '85s' && $target ne '86p' && $target ne '73p') { + print "ERROR: Invalid target file type.\n"; + exit 1; +} + +#check if binfile is present, and open it if it is +if ( -e $infile ) { + open INFILE, $infile or die "ERROR: Could not open $infile: $!"; + binmode INFILE; + print "Converting to $target...\n"; +} +else { + print "ERROR: $infile not found.\n"; + exit 1; +} + +my $binsize = -s $infile; +my $datasize = $binsize + 20; +my $varsize = $binsize + 5; +my $shortvarsize = $varsize - 2; +my $buffer; + +#generate on-calculator name +my $oncalcname = substr $ARGV[1], 0, -4; +$oncalcname = uc($oncalcname); #convert to uppercase +$oncalcname = pack('A7', $oncalcname) if ($target eq '82p'); #truncate or append to 7 chars +$oncalcname = pack('A8', $oncalcname) if ($target eq '83p'); +print "$oncalcname check\n"; +#print "$binsize\n"; +open OUTFILE, ">$outfile" or die $!; +binmode OUTFILE; + +if ($target eq '82p') { + #write header + print OUTFILE "**TI82**", pack('c3',26,10,0), "packed with oysterpac", pack('c21',0); + print OUTFILE pack('s<',$datasize), pack('c2',11,0), pack('s<',$varsize); + print OUTFILE pack('s<',56326); + print OUTFILE "$oncalcname"; #, pack('c2',0,45); #test - after the name it works like this: one 0 - if not 7 bytes, ascii minus, then # of bytes missing + print OUTFILE pack('s<',$varsize), pack('s',$shortvarsize); + print OUTFILE pack('s<',213),pack('c1',17); + + #copy binfile + while ( + read (INFILE, $buffer, $binsize) + and print OUTFILE $buffer + ){}; + die "ERROR: Problem copying: $!\n" if $!; + + #calculate checksum + my $checksum = 0; + my ($byteval, $i); + + close OUTFILE; + open INFILE2, $outfile; + binmode INFILE2; + my $checksize = -s $outfile; + + for ($i = 60; $i < $checksize; $i++) { + sysseek(INFILE2, $i, 0) or die $!; + sysread(INFILE2, $byteval, 1) == 1 or die $!; + $checksum = $checksum + ord($byteval); + } + close INFILE2; + open OUTFILE, ">>$outfile" or die $!; + binmode OUTFILE; + $checksum = $checksum - 86; + print OUTFILE pack('s<',$checksum); +} + +if ($target eq '83p') { + #write header + print OUTFILE "**TI83**", pack('c3',26,10,0), "packed with oysterpac", pack('c21',0); + print OUTFILE pack('s<',$datasize), pack('c2',11,0), pack('s<',$varsize); + #print OUTFILE pack('s<',56326); #0xdc06 + print OUTFILE pack('c1',6); + print OUTFILE "$oncalcname"; #, pack('c2',0,45); #test - after the name it works like this: one 0 - if not 7 bytes, ascii minus, then # of bytes missing + print OUTFILE pack('s<',$varsize), pack('s',$shortvarsize); + print OUTFILE pack('s<',213),pack('c1',17); + + #copy binfile + while ( + read (INFILE, $buffer, $binsize) + and print OUTFILE $buffer + ){}; + die "ERROR: Problem copying: $!\n" if $!; + + #calculate checksum + my $checksum = 0; + my ($byteval, $i); + + close OUTFILE; + open INFILE2, $outfile; + binmode INFILE2; + my $checksize = -s $outfile; + + for ($i = 60; $i < $checksize; $i++) { + sysseek(INFILE2, $i, 0) or die $!; + sysread(INFILE2, $byteval, 1) == 1 or die $!; + $checksum = $checksum + ord($byteval); + } + close INFILE2; + open OUTFILE, ">>$outfile" or die $!; + binmode OUTFILE; + $checksum = $checksum - 86; + print OUTFILE pack('s<',$checksum); +} + +close INFILE; +close OUTFILE; \ No newline at end of file