/******************************************************************************* * TIANO.S - by David Kühling 1998 *--------------------------------------------------------------------------- * * This is a programm, which lets you play tones through the serial port of * the TI-92 by pressing different keys. For that purpose it uses the sound * routines of Soundlib. For further information look Soundlib.h. * * This file needs to be preprocessed by the PreFargo preprocessor. You can * get this programm from http://www.ticalc.org, somewhere in the dosutilities * section. If you can't find it, (e)mail me. * * Last modification: 14th july 1998 * * Contacting me: * Email: dkuehlin@hell1og.be.schule.de (don't mix up 'l' and '1') * - valid till june 2000 * Mail: * David Kühling * Lion-Feuchtwanger-Str. 44 * 12619 Berlin * GERMANY */ #include #include #include XDEF _main XDEF _comment #define near(variable) variable-NEAR_DATA(a4) #define neari(variable,index) variable-NEAR_DATA(a4,index) /******************************************************************************* * Displays texts, and the piano's keyboard * Destroys registers! */ SmallKbdY EQU 22 BigKbdY EQU 60 ExitTxtY EQU 104 ExitTxtX EQU 5 DispX EQU 110 DispY EQU 60 DispW EQU 120 DispH EQU 32 DispValueX EQU DispX+DispW-3 Disp1stLineY EQU DispY+3 Disp2ndLineY EQU Disp1stLineY+10 Disp3rdLineY EQU Disp2ndLineY+10 BuildScreen: jsr flib::clr_scr lea tios::DrawStrXY, a6 // load addresses of frequently used routines lea flib::frame_rect, a5 lea tios::FontSetSys, a4 lea tios::DrawCharXY, a3 /***** display title bar and border *****/ // BYTE FontSetSys(BYTE font) move.w #1, -(a7) jsr (a4) // 2 bytes on stack // void DrawStrXY(WORD x, WORD y, BYTE *string, WORD color) move.w #4, -(a7) pea Title(PC) move.l #$000D0001, -(a7) jsr (a6) // 12 bytes on stack lea tios::main_lcd, a0 // invert title bar move.w #74, d7 // invert 75 longwords = 10 lines \Loop0: not.l (a0)+ dbra d7, \Loop0 // frame_rect(rect r) clr.l d7 // draw screen borders move.l #$00EF0079, -(a7) // push x2 and y2 move.l d7, -(a7) // push x1 and y1 (both 0) jsr (a5) // 20 bytes on stack /****** display "[ESC]: Exit" ******/ // void DrawStrXY(WORD x, WORD y, BYTE *string, WORD color) move.w #4, -(a7) pea ExitTxt(PC) move.l #ExitTxtX*65536+ExitTxtY, -(a7) jsr (a6) // 30 bytes on stack /****** display the Display Texts ******/ moveq #10, d7 // row height // frame_rect(rect r) move.l #65536*(DispX+DispW)+DispY+DispH, -(a7) // x2;y2 move.l #65536*DispX+DispY, -(a7) // x1;y1 jsr (a5) // 38 bytes on stack // void DrawStrXY(WORD x, WORD y, BYTE *string, WORD color) move.w #4, -(a7) pea DispTxt1(PC) move.l #65536*(DispX+2)+Disp1stLineY, -(a7) jsr (a6) addq.l #8, a7 // change x, y and *string pea DispTxt2(PC) add.l d7, -(a7) // to next row jsr (a6) addq.l #8, a7 // change x, y and *string pea DispTxt3(PC) add.l d7, -(a7) jsr (a6) // 48 bytes on stack /****** display the small keaboard ******/ /*** upper part ***/ moveq #9, d7 // y-counter lea tios::main_lcd+1+SmallKbdY*30, a0 // load address of left,top corner \Loop1: moveq #3, d6 // x-counter \Loop2: moveq #6, d5 // byte-counter lea SmallKbd1(PC), a1 \Loop3: move.b (a1)+, (a0)+ dbra d5, \Loop3 dbra d6, \Loop2 addq.l #2, a0 // to next line dbra d7, \Loop1 /*** lower part ***/ moveq #5, d7 // y-counter \Loop4: moveq #27, d6 // x-counter \Loop5: move.b (a1), (a0)+ dbra d6, \Loop5 addq.l #2, a0 // to next line dbra d7, \Loop4 // frame_rect(rect r) move.l #$E70000+SmallKbdY+16, -(a7) // x2;y2 move.l #$070000+SmallKbdY-1, -(a7) // x1;y1 jsr (a5) // 56 bytes on stack /*** text ***/ lea SmallKbdText(PC), a2 // Octave descriptions moveq #6, d7 // x-counter moveq #16, d6 // x-position \Loop6: // void DrawStrXY(WORD x, WORD y, BYTE *string, WORD color) move.w #4, -(a7) pea (a2) move.w #SmallKbdY+18, -(a7) move.w d6, -(a7) jsr (a6) addi.w #28, d6 // next octave addq.l #3, a2 dbra d7, \Loop6 // 126 bytes on stack /****** display the big keaboard ******/ /*** upper part ***/ moveq #19, d7 // y-counter lea tios::main_lcd+1+BigKbdY*30, a0 // load address of left,top corner \Loop7: moveq #6, d6 // x-counter lea BigKbd1(PC), a1 \Loop8: move.b (a1)+, (a0)+ dbra d6, \Loop8 lea 23(a0), a0 // to next line dbra d7, \Loop7 /*** lower part ***/ moveq #11, d7 // y-counter \LoopA: moveq #6, d6 // x-counter \LoopB: move.b (a1), (a0)+ dbra d6, \LoopB lea 23(a0), a0 // to next line dbra d7, \LoopA // frame_rect(rect r) move.l #$3F0000+BigKbdY+32, -(a7) // x2;y2 move.l #$070000+BigKbdY-1, -(a7) // x1;y1 jsr (a5) // 134 bytes on stack /*** text (white keys) ***/ moveq #6, d7 // x-counter moveq #8, d6 // x-position clr.l d5 // d5 = #$000000FF (what2 and what3) subq.b #1, d5 lea BigKbdText1(PC), a2 \LoopC: // void DrawCharXY(BYTE ch, WORD x, WORD y, WORD color, WORD what1, WORD what2, WORD what3) move.l d5, -(a7) // what2, what3 (d5 = $000000FF) move.l #$000400FF, -(a7) // color, what1 move.w #BigKbdY+24, -(a7) // y move.w d6, -(a7) // x clr.w d0 // ch move.b (a2)+, d0 move.w d0, -(a7) jsr (a3) addq.l #8, d6 dbra d7, \LoopC // 242 bytes on stack /*** text (black keys) ***/ moveq #4, d7 // x-counter moveq #13, d6 // x-position // BYTE FontSetSys(BYTE font) move.w #0, -(a7) jsr (a4) // 234 bytes on stack \LoopD: // void DrawCharXY(BYTE ch, WORD x, WORD y, WORD color, WORD what1, WORD what2, WORD what3) clr.w d0 move.b (a2)+, d0 // if (!ch) continue bne \LoopD_DoCh addq.w #8, d6 bra \LoopD \LoopD_DoCh: move.l d5, -(a7) // what2, what3 (d5 = $00000FF) move.l d5, -(a7) // color, what1 (d5 = $00000FF) move.w #BigKbdY+8, -(a7) // y move.w d6, -(a7) // x move.w d0, -(a7) // ch jsr (a3) addq.l #8, d6 dbra d7, \LoopD // 304 bytes on stack // BYTE FontSetSys(BYTE font) move.w #1, -(a7) jsr (a4) // 306 bytes on stack lea 306(a7), a7 // remove all those arguments rts /******************************************************************************* * little pause for keyboard matrix accesses */ IOPause: move.l (a7), (a7) move.l (a7), (a7) move.l (a7), (a7) rts /******************************************************************************* * MAIN */ Duration EQU 40 // Duration of a tone (milliseconds) when a key // is pressed once _main: move.w #$700, d0 // disable interrupts trap #1 jsr soundlib::Init // initialize Soundlib bsr BuildScreen // draw the programm screen /** * Registers: * d3.w = octave * d4.w = tone * d5.w = duration of current tone * a2.l = 600018 (* keyboard row mask) * a3.l = 60001B (* keyboard column mask) * a4.l = *NEAR_DATA * a6.l = *DrawStrXY (watch BuildScreen) */ moveq #4, d3 // octave = 4 clr.w d4 // tone = 0 clr.w d5 // duration = 0 lea $600018, a2 // a2 = * row mask lea 3(a2), a3 // a3 = * column mask lea NEAR_DATA(PC), a4 bra \DisplayOctaveNumber \MainLoop: /****** check the octave keys [F1]...[F7] ******/ moveq #6, d7 // d7 = octave counter (#6 = F7, #5 = F6, #4 = F5...) lea near(OctaveKeys), a0 \OctaveLoop: moveq #-1, d0 // d0 = row mask move.b (a0)+, d1 // d1 = row number bclr.l d1, d0 // clear the corresponding bit in the row mask move.w d0, (a2) // set the row mask bsr IOPause // allow the I/O to recover btst #4, (a3) // test the key dbeq d7, \OctaveLoop // break, if key was pressed or octave = 0 bne \NoOctaveKey cmp.w d7, d3 beq \NoOctaveKey move.w d7, d3 tst.w d4 // if tone != -1 (if tone is not pause) bmi \TonePause clr.w d5 // duration = 0; \TonePause: \DisplayOctaveNumber: /** display the octave's number **/ lea near(OctaveString), a0 // OctaveString[0] = '0' + octave move.b #'0', (a0) add.b d3, (a0) // void DrawStrXY(WORD x, WORD y, BYTE *string, WORD color) move.w #4, -(a7) pea (a0) move.l #Disp1stLineY+(DispValueX-6)*65536, -(a7) jsr (a6) // ´10 bytes on stack lea 10(a7), a7 \NoOctaveKey: /****** check the tone keys (sdfghjkeryui) ******/ moveq #11, d7 // d7 = tone counter ( #11 = B, #10 = A#...) lea near(ToneKeys), a0 \ToneLoop: moveq #-1, d0 // d0 = row mask clr.w d1 // d1.w = column_number + 16*row_number move.b (a0)+, d1 ror.w #4, d1 // d1.b = row number bclr.l d1, d0 // clear the corresponding bit in the row mask move.w d0, (a2) // set the row mask bsr IOPause // allow the I/O to recover clr.b d1 // d1.b = column number rol.w #4, d1 btst.b d1, (a3) // test the key dbeq d7, \ToneLoop // break, if key was pressed or tone = 0 cmp.w d4, d7 // check, whether tone has changed beq \SameTone /** tone has changed **/ move.w d7, d4 // set the new tone clr.w d5 // duration = 0 /** display the tone's name **/ lsl.w #1, d7 // *ToneString = ToneName[Tone] move.w neari(ToneNames,d7.w), near(ToneString) // void DrawStrXY(WORD x, WORD y, BYTE *string, WORD color) move.w #4, -(a7) pea near(ToneString) move.l #Disp2ndLineY+(DispValueX-12)*65536, -(a7) jsr (a6) // 10 bytes on stack lea 10(a7), a7 \SameTone: /******* play the tone / pause ******/ tst.w d4 // if tone = -1: no tone (pause) bmi \NoTone move.w d3, d0 // calculate the tone number mulu #12, d0 // d0 = tone_number = octave*12+tone add.w d4, d0 moveq #Duration, d1 lea soundlib::FrqTable, a0 // d0 = frequency = soundlib::FrqTable[tone_number] lsl.w #1, d0 move.w 0(a0, d0.w), d0 jsr soundlib::Sound bra \ToneDone \NoTone: moveq #Duration, d1 // if no tone: just pause jsr soundlib::Pause /****** current tone's duration ******/ \ToneDone: addq.w #1, d5 // duration = ++duration == 100 ? 0 : duration; cmpi.w #100, d5 bne \DurationOk clr.w d5 \DurationOk: /** display the duration **/ move.w d5, d0 // d0 = duration (working register) ext.l d0 lea near(DurationString), a0 move.w #"00", (a0) // sprintf (DurationString, "%02i", duration); divu #10, d0 add.b d0, (a0) swap d0 add.b d0, 1(a0) // void DrawStrXY(WORD x, WORD y, BYTE *string, WORD color) move.w #4, -(a7) pea (a0) move.l #Disp3rdLineY+(DispValueX-12)*65536, -(a7) jsr (a6) // 10 bytes on stack lea 10(a7), a7 /****** Check [ESC], and exit if pressed ******/ move.w #$3FF-$100, (a2) // set the row mask bsr IOPause // allow the I/O to recover btst #6, (a3) // check the key bne \MainLoop // continue, if not pressed clr.w d0 // enable interrupts trap #1 rts /******************************************************************************* * DATA */ Title: dc.b "TIano " _comment: dc.b "v1.00 - by David Kühling 1998", 0 /** Small Keyboard **/ SmallKbd1: dc.b %00111011, %10010011, %10111011, %10010011, dc.b %10111001, %00111011, %10111001 SmallKbd2: dc.b %00010001 SmallKbdText: dc.b "F1",0, "F2",0, "F3",0, "F4",0, "F5",0, "F6",0, "F7",0 /** Big Keyboard **/ BigKbd1: dc.b %00000111, %11000111, %11000001, %00000111, %11000111, %11000111, %11000000 BigKbd2: dc.b %00000001 BigKbdText1: dc.b 's', 'd', 'f', 'g', 'h', 'j', 'k' BigKbdText2: dc.b 'E', 'R', 0, 'Y', 'U', 'I' ExitTxt: dc.b "[ESC]: Exit", 0 /** Displays **/ DispTxt1: dc.b "Octave:", 0 DispTxt2: dc.b "Tone:", 0 DispTxt3: dc.b "Duration:", 0 ds.w 0 NEAR_DATA: /** Tone names **/ dc.b "--" ToneNames: dc.b "C " dc.b "C#" dc.b "D " dc.b "D#" dc.b "E " dc.b "F " dc.b "F#" dc.b "G " dc.b "G#" dc.b "A " dc.b "A#" dc.b "B " dc.b "C " ToneString: dc.b " ", 0 OctaveString: dc.b "0", 0 ds.w 0 DurationString: dc.b "00", 0 /** Key Data **/ OctaveKeys: dc.b 3, 5, 7, 9, 2, 4, 6 // rows of [F7]..[F1] ToneKeys: dc.b 2+7*16 // [K] dc.b 3+7*16 // [I] dc.b 2+6*16 // [J] dc.b 3+6*16 // [U] dc.b 2+5*16 // [H] dc.b 3+5*16 // [Y] dc.b 2+4*16 // [G] dc.b 2+3*16 // [F] dc.b 3+3*16 // [R] dc.b 2+2*16 // [D] dc.b 3+2*16 // [E] dc.b 2+1*16 // [S] END