gregg@okstate.UUCP (02/16/85)
The following note contains the TMS/9900 sources to the Extended Basic equivalents of the DSRLNK & GPLLNK subroutines found in the Editor/Assembler module for the TI 99/4A. This code contains some uniquely machine dependent code. Different versions of the console GROM require some slight modifcations to the values defined in the EQU statements. The call to DSRLNK does support GROM based DSR's unlike the version in the E/A module. This means that you can access the cassette just like you would a DISK, or the RS-232. Any questions, comments, flames can be mailed to me at the address below. Enjoy... Gregg Wonderly Department of Computing and Information Sciences Oklahoma State University 1 /|\ UUCP: {cbosgd, ea, ihnp4, isucs1, mcvax, uokvax}!okstate!gregg | | _______//|\\_______ |_|_|_|_||_||_|_|_|_| |_|_|_|_||_||_|_|_|_| |_|_|_|_|||||_|_|_|_| ARPA: gregg%okstate.csnet@csnet-relay.arpa ------------------------------------------------------------------------------ * * DSRLNK and GPLLNK equivalents for the TI 99/4A under Extended-Basic * TITL 'GPLLNK & DSRLNK' * DEF GPLLNK,DSRLNK * * SYSTEM EQUATES. * * THESE ROUTINES !!MUST!! BE LOADED FIRST IN ORDER FOR YOU TO REFERENCE * THE ROUTINES. IF NOT, THAN YOU WILL HAVE TO WRITE CODE TO LOOK THE * NAMES AND ADDRESS UP IN THE DEF TABLE. * DEFPTR EQU >2004 ADDRESS OF POINTER TO DEF TABLE. LNKENT EQU >205A THE "LINK" ENTRY POINT. LNKCON EQU >205E WHERE TO REJOIN THE "LINK" CODE. SYSWS EQU >2038 SYSTEM WORKSPACE. GRMRA EQU >9802 GROM READ ADDRESS REGISTER. SETGRM EQU >60 ADDRESS IN ROM WHERE R6 GETS WRITEN TO GROMAD. GPLWS EQU >83E0 GPL WORKSPACE. GPLR6 EQU >83EC GPL REGISTER R6. DATSTK EQU >8373 BYTE OFFSET INTO PAD OF THE SYSTEM DATA STACK. PAD EQU >8300 ADDRESS OF PAD ITSELF. STATUS EQU >837C * * PUT BRANCH TO PATCH CODE AT START OF "LINK" SUBPROGRAM ENTRY. * AORG LNKENT B @CHKFLG THIS WRITES OVER AN INSTRUCTION! * * THE CODE NECESSARY TO DISTINGUISH "GPLLNK" FROM "LINK" ENTRIES. * THE AORG'D DATA ABOVE WRITES OVER THE FOLLOWING MOVe INSTRUCTION, SO * WE WILL PUT IT HERE. THIS IS VERY MACHINE DEPENDENT, BUT WHAT THE HECK. * RORG CHKFLG MOV @DEFPTR,R1 THIS INSTRUCTION WAS AT "LNKENT". ABS @SYSFLG IF NOT "LINK" CALL THEN JNE NOTLNK GOTO "NOTLNK" B @LNKCON ELSE REJOIN THE "LINK" CODE. * * IT IS A LINK REENTRY SO RESTORE THE OLD WORKSPACE AND RETURN TO THE CALLER. * NOTLNK CLR @SYSFLG RESET "GPLLNK" FLAG. LWPI SYSWS LOAD "GPLLNK" WORKSPACE FOR RETURN. RTWP RETURN TO USER PROGRAM. * * ACTUAL "GPLLNK" ROUTINE. * ACCESSED WITH: * * GPLLNK EQU >250E * BLWP @GPLLNK * DATA=ADDRESS OF GPL ROUTINE AS IN E/A MANUAL. * * THIS FLAG IS USED TO TELL US IF THE BRANCH THROUGH LINK IS A RETURN FROM * A GPL CALL, OR AN ACTUAL CALL TO "LINK". * SYSFLG DATA 0 "GPLLNK" FLAG. * * GPLLNK DATA SYSWS,$+2 CONTEXT VECTOR FOR "GPLLNK". SETO @SYSFLG SET GPLLNK FLAG TO CATCH THE PROCESSOR ON RETURN. * * AT THIS POINT, THE GROM ADDRESS MUST HAVE BEEN SET UP PREVIOUSLY, * OR IT MUST BE UNALTERED FROM THE TIME THAT EX_BASIC PASSED CONTROL. * IF YOU DESIRE, THE ADDRESS CAN BE RETREIVED AT ENTRY TO YOUR ROUTINE, * AND THEN YOU CAN MODIFY THE NEXT 4 LINES TO PUSH THAT ADDRESS - 2. * BL @SVEGRM * * THE FOLLOWING CODE IS ROM DEPENDENT. SHOULD WORK ON CURRENT MODELS. * MOV *R14+,@GPLR6 MOVE ROUTINE ADDRESS TO GPLWS REGISTER 6 LWPI GPLWS GPL WORKSPACE NECESSARY FOR ALL GPL ROUTINES B @SETGRM SET GROM ADDRESS TO VALUE IN R6 AND GO. * * THE ACTUAL DSRLNK CODE. CAN BE CALLED WITH: * * DSRLNK EQU >2522 * BLWP @DSRLNK * DATA (8, OR 10) FOR EITHER A DSR CALL, OR A SUBPROGRAM CALL. * DSRLNK DATA SYSWS,$+2 SETO @SYSFLG MOV *R14+,R2 LI R3,>0070 CI R2,>0008 JEQ DSR LI R3,>464D DSR BL @SVEGRM MOV R3,R1 BL @PUSH MOVB R1,@STATUS LWPI GPLWS LI R6,>0010 B @SETGRM * * GET GROM ADDRESS AND RESTORE TO THE VALUE OF THE CALL TO "LINK". * SVEGRM MOVB @GRMRA,R1 SWPB R1 MOVB @GRMRA,R1 SWPB R1 * * WE USE -3 HERE BECAUSE THE GPL INSTRUCTION THAT WILL RETURN US TO THE * LINK ENTRY POINT IS 2 BYTES LONG. THE -1 MORE COMES FROM THE FACT * THAT THE GROM INCREMENTS WHEN WE READ THE ADDRESS, SO WE MUST SUBTRACT * 1 TO ACCOUNT FOR THIS AND GET THE ACTUAL ADDRESS. * AI R1,-3 * * PUSH WORD IN R1 ONTO THE SYSTEM/GPL DATA STACK. * PUSH INCT @DATSTK MOVB @DATSTK,R4 SRL R4,8 MOVB R1,@PAD(R4) SWPB R1 MOVB R1,@PAD+1(R4) SWPB R1 RT END ---------------------------------------------------------------------------- * * This is a test program to show how the GPLLNK and DSRLNK routines * are used. If this program does not run properly, than you will need * to establish the GROM addresses of the proper DSRLNK data bytes. * TITL 'DSR/GPL-LNK TEST PROGRAM' * DEF START * REF GPLLNK,VSBW,VSBR,VMBW,VMBR,VWTR CHKBRK EQU >0020 GPLLNK EQU >250E DSRLNK EQU >2526 XMLLNK EQU >2018 KSCAN EQU >201C VSBW EQU >2020 VSBR EQU >2028 VMBR EQU >202C VMBW EQU >2024 VWTR EQU >2030 * * NUMCOL EQU 28 SCRWTH EQU 32 SPACE EQU >8080 PAD EQU >8300 THE ADDRESS OF THE SCRATCH PAD RAM. FAC EQU >834A SCRVAL EQU 0 VDP REGISTER 2 VALUE. SCRADR EQU SCRVAL*>400 ACTUAL ADDRESS OF THE SCREEN TABLE. CHRVAL EQU 0 VDP REGISTER 4 VALUE. CHRADR EQU CHRVAL*>800 ACTUAL ADDRESS OF THE PATTERN TABLE. BEEP EQU >34 GPL ADDRESS OF ACCEPT TONE CODE. BONK EQU >36 GPL ADDRESS OF BAD RESPONSE TONE CODE. * * START OF PROGRAM * START LWPI MYWS LIMI 0 * * SET VDP REGISTERS TO VALUES IN THE TABLE ABOVE. * BL @SETVDP STORE THE VALUES. DATA VDPDAT * * START DEMO * BLWP @CLS CLEAR THE SCREEN. BLWP @PRINT PRINT THE FIRST MESSAGE. DATA BEEPY BLWP @SCROLL SCROLL UP ONE LINE. BLWP @SCROLL SCROLL UP ONE LINE. BLWP @DELAY PAUSE FOR A SECOND OR SO. DATA 70 BLWP @GPLLNK SOUND THE BEEP. DATA BEEP LIMI 2 ENABLE INTERRUPTS TO LET SOUND GO. BLWP @DELAY WAIT FOR SOUND TO FINISH DATA 200 LIMI 0 TURN INTERRUPTS OFF. BLWP @PRINT PRINT THE SECOND MESSAGE. DATA BEEPN BLWP @SCROLL SCROLL UP A LINE. BLWP @SCROLL SCROLL UP A LINE. BLWP @DELAY PAUSE FOR A SECOND OR SO. DATA 70 BLWP @GPLLNK SOUND THE BONK. DATA BONK LIMI 2 TURN INTERRUPTS ON TO LET SOUND GO. BLWP @DELAY WAIT FOR THE SOUND TO FINISH. DATA 200 LIMI 0 TURN INTERRUPTS OFF. BLWP @PRINT PRINT FLOATING POINT MESSAGE. DATA FLTMES BLWP @SCROLL SCROLL UP A LINE. LI R1,4 MOVE 4 WORDS. LI R2,FLOAT LOAD SOURCE ADDRESS. LI R3,FAC LOAD THE DESTINATION ADDRESS. MVFLT MOV *R2+,*R3+ MOVE 2 BYTES. DEC R1 ANY LEFT? JGT MVFLT LOOP UNTIL DONE. MOVB R1,@FAC+11 MOVE A ZERO BYTE TO FLAG TI-BASIC FORMAT. BLWP @GPLLNK CONVERT IT TO A ASCII STRING. DATA >14 MOVB @FAC+12,R2 GET THE LENGTH OF THE STRING. SRL R2,8 MAKE IT A BYTE. MOVB @FAC+11,R1 GET THE BASE ADDRESS OF THE STRING IN PAD SRL R1,8 MAKE IT A BYTE. AI R1,PAD GET ABSOLUTE ADDRESS. BLWP @ADDSTR ADD THE STRING TO THE DISPLAY. LI R1,3 3 LINES TO SCROLL. SCRL3 BLWP @SCROLL SCROLL ONCE. DEC R1 ANY LEFT? JGT SCRL3 BLWP @DELAY WAIT AGAIN. DATA 300 BLWP @PRINT PRINT MESSAGE ABOUT OPENING A FILE. DATA OPNMSG BLWP @SCROLL SCROLL! BLWP @SCROLL "" LI R1,85+9+NMELEN LENGTH OF PAB AND DATA BUFFER. MOV R1,@>830C PUT LENGTH WHERE "GETSTR" CAN FIND IT. LI R2,12+NMELEN GET LENGTH OF JUST PAB + A COUPLE OF BYTES. * * BLWP @PRINT PRINT DEBUG MESSAGE. * DATA TRYALC * BLWP @SCROLL * BLWP @XMLLNK CALL "GETSTR" IN EX_BASIC ROM. DATA >02 * * BLWP @PRINT PRINT DEBUG MESSAGE. * DATA TRYSUC * BLWP @SCROLL * * THE CODE IN STRASG INDICATES THAT IF >830C IS ZERO THAN * WE ARE OUT OF MEMORY. * MOV @>830C,R0 CHECK FOR OUT OF MEMORY. JNE CONT B @ABORT * CONT MOV @>831C,R0 GET THE ADDRESS OF THE SPACE WE ACTUALLY GOT. MOV R0,R8 GET ADDRESS OF THE ERROR BYTE IN THE PAB INC R8 PUT THIS VALUE IN R8 FOR LATER USE. MOV R0,R9 GET ADDRESS OF DATA BUFFER IN R9. A R2,R9 LI R1,PABDSC GET ADDRESS OF DATA TO MOVE TO VDP RAM BLWP @VMBW MOVE THE PAB TO OUR BUFFER. MOV R0,R10 GET THE ADDRESS OF THE LENGTH BYTE IN R10. AI R10,9 ADD 9 TO ADDRESS OF THE PAB TO GET IT. STWP R1 GET ADDRESS OF THE ADDRESS IN R1 TO PUT IN PAB. AI R1,18 GET ADDRESS OF R9 IN CURRENT WP. LI R2,2 WRITE 2 BYTES. INCT R0 POINT AT DATA BUFFER ADDRESS AREA IN PAB. BLWP @VMBW * * BLWP @PRINT PRINT DEBUG MESSAGE. * DATA PABMOV * DATA SCROLL * MOV R10,@>8356 TELL DSRLNK WHERE THE PAB IS. BLWP @DSRLNK TRY TO OPEN THE FILE. DATA 8 MOV R8,R0 GET THE ADDRESS OF THE ERROR BYTE. BLWP @VSBR ANDI R1,>E000 STRIP EVERYTHING BUT THE ERROR BITS. JEQ OPENED IF ZERO LEFT THEN NO ERRORS. * BLWP @SCROLL PRINT THE ERROR MESSAGE. BLWP @PRINT DATA CNTOPN BLWP @SCROLL SCROLL UP. BLWP @SCROLL "" BLWP @GPLLNK SOUND A BONK FOR ERROR. DATA BONK JMP ABORT QUIT WHILE WE ARE AHEAD. * OPENED MOV R8,R0 GET THE ADDRESS OF THE I/O OPCODE BYTE. DEC R0 LI R1,>0200 STORE A READ OPCODE. BLWP @VSBW BLWP @GPLLNK SOUND A BEEP FOR REASURENCE. DATA BEEP * LIMI 2 BLWP @DELAY DATA 40 LIMI 0 * READIT MOV R10,@>8356 TELL DSRLNK WHERE WE HAVE THE PAB AGAIN. BLWP @DSRLNK READ A RECORD. DATA 8 MOV R8,R0 GET THE ERROR BYTE. BLWP @VSBR ANDI R1,>E000 ANY ERROS YET? JNE CLOSE CLOSE IF ERRORS PRESENT. MOV R9,R0 GET THE ADDRESS OF THE BUFFER. LI R1,DATBUF WHERE TO PUT THE STRING FOR PRINTING. BLWP @SCROLL GET A NEW LINE. LI R2,80 HOW MANY BYTES TO MOVE. BLWP @VMBR READ THEM INTO THE BUFFER. MOV R8,R0 GET THE ADDRESS OF THE BYTE COUNT. C *R0+,*R0+ ADD 4 TO THE ADDRESS OF THE ERROR BYTE TO GET IT BLWP @VSBR READ THE LENGTH BYTE INTO R1. MOV R1,R2 PUT IT IN R2 FOR THE "ADDSTR" ROUTINE. LI R1,DATBUF GET THE DATA BUFFER ADDRESS BACK. SRL R2,8 MAKE THE COUNT INTO A BYTE VALUE. BLWP @ADDSTR GO PRINT THE STRING. * BL @CHKBRK IN FCTN 4 BEING PRESSED? JEQ CLOSE GO IF BREAK PRESSED. CLR @>8374 KEYSCN BLWP @KSCAN CHECK THE KEYBOARD AND PAUSE IF A KEY IS PRESSED MOVB @>8375,R1 GET THE KEY. SRA R1,8 MAKE IT A FULL WORD (SIGN EXTEND). CI R1,>FFFF WAS THERE A KEY PRESSED. JNE KEYSCN SCAN AGAIN IF SO. JMP READIT GO DO IT AGAIN. * CLOSE MOV R8,R0 GET THE ADDRESS OF THE I/O OPCODE. DEC R0 LI R1,>0100 GET THE CLOSE OPCODE TO WRITE THERE. BLWP @VSBW WRITE IT. BLWP @SCROLL PRINT THE MESSAGE ABOUT EOF. BLWP @SCROLL BLWP @PRINT DATA EOF BLWP @SCROLL PRINT SOME WHITE SPACE. BLWP @SCROLL BLWP @GPLLNK SOUND A BEEP FOR REASURANCE. DATA BEEP MOV R10,@>8356 TELL DSRLNK WHERE THE PAB IS AT. BLWP @DSRLNK CLOSE THE FILE. DATA 8 ABORT BL @SETVDP SET VDP BACK TO ITS ORIGINAL STATE. DATA EXVDAT LWPI >83E0 RETURN THROUGH THE GPL INTERPRETER. B @>6A ****************************************************************** * * SUPPORT ROUTINES FOR THE ABOVE PROGRAM. * ****************************************************************** * * LOAD 8 BYTES INTO THE VDP REGISTERS. * ****************************************************************** SETVDP LI R1,8 8 REGISTERS TO SET. CLR R0 START WITH REGISTER ZERO. MOV *R11+,R2 GET THE ADDRESS OF THE BYTES. LIMI 0 INTERRUPTS MUST BE OFF. MOVB @1(R2),@>83D4 STORE VDP R1 FOR AUTO BLANK RESTORE. SVDP01 MOVB *R2+,R0 GET A VALUE. SWPB R0 SWAP LSB WITH MSB TO ALLIGN THE VALUES. BLWP @VWTR WRITE THE VALUE TO THE REGISTER. AI R0,>0100 GET THE NUMBER OF THE NEXT REGISTER. SWPB R0 SWAP BYTES FOR THE MOVB AT THE TOP OF THE LOOP SVDP02 DEC R1 ANY LEFT? JGT SVDP01 LOOP IF THERE ARE. RT RETURN TO THE CALLER. ****************************************************************** * * PAUSE FOR A WHILE, MAGICAL NUMBERS USED. * ****************************************************************** DELAY DATA SUBWS1,$+2 MOV *14+,R1 GET THE OUTER LOOP COUNT. DEL010 LI R0,1000 INNER LOOP GOES 1000 TIMES. DEL020 DEC R0 COUNT DOWN. JGT DEL020 LOOP IF NOT ZERO. DEC R1 GO UNTIL DURATION EXPIRES. JGT DEL010 RTWP RETURN TO THE CALLER. ****************************************************************** * * CLEAR A "SCRWTH" COLUMN BY 24 ROW SCREEN. * ****************************************************************** CLS DATA SUBWS1,$+2 LI R0,SCRADR GET THE START OF THE SCREEN. LI R1,SPACE GET SPACES TO WRITE. LI R2,SCRWTH*24-1 COUNT OF CHARATERS TO WRITE IN THE LOOP. BLWP @VSBW WRITE ONE TO SET ADDRESS IN VDP. CLS010 MOVB R1,@>8C00 WRITE THE REST CONSECUTIVELY. DEC R2 ANY LEFT? JGT CLS010 RTWP RETURN TO THE CALLER. ****************************************************************** * * ENTRY POINT TO ADD A STRING TO THE SCREEN AT THE CURRENT CURSOR * POSITION. R1 IS THE ADDRESS OF THE STRING. * R2 IS THE LENGTH. * ****************************************************************** ADDSTR DATA SUBWS1,$+2 MOV @2(R13),R7 MOV @4(R13),R8 JMP PRT010 ****************************************************************** * * ENTRY POINT TO PRINT A STRING IN BASIC FORMAT ON THE SCREEN AT THE * CURRENT CURSOR POSITION. THE FIRST BYTE IS THE LENGTH. * ****************************************************************** PRINT DATA SUBWS1,$+2 MOV *R14+,R7 GET THE STRING TO PRINT. MOVB *R7+,R8 GET THE LENGTH OF THE THING. SRL R8,8 MAKE IT A BYTE VALUE. PRT010 ABS @CURCOL ARE WE AT THE END OF THE LINE? JNE NOSCRL DON'T SCROLL IF NOT. BLWP @SCROLL SCROLL IF WE ARE AT THE END OF THE LINE. NOSCRL MOVB *R7+,R1 GET A BYTE. LI R0,SCRWTH*24+SCRADR-2 GET THE LINE OF THE SCREEN TO DISPLAY ON. S @CURCOL,R0 WHAT COLUMN ARE WE ON? DEC @CURCOL POINT TO NEXT. AI R1,>6000 GET BASIC OFFSET. BLWP @VSBW PRINT A CHARACTER. DEC R8 ANY LEFT? JNE PRT010 RTWP RETURN TO THE CALLER. ****************************************************************** * * SCROLL A SCRWTH COLUMN SCREEN UP ONE LINE. * ****************************************************************** SCROLL DATA SUBWS2,$+2 BLWP @XMLLNK USE ROM ROUTINE IN EX_BASIC MODULE. DATA >26 DATA FOR CALL. LI R0,NUMCOL SET BACK TO COLUMN 1. MOV R0,@CURCOL RTWP RETURN TO CALLER. ****************************************************************** * * WORKSPACES AND OTHER STORAGE. * ****************************************************************** MYWS BSS 32 MAIN WORKSPACE SUBWS1 BSS 32 FIRST LEVEL WORKSPACE. SUBWS2 BSS 32 SECOND LEVEL WORKSPACE. CURCOL DATA 0 CURRENT COLUMN ON THE SCREEN. ****************************************************************** * * VDP TABLES * ****************************************************************** VDPDAT BYTE 0,>E0,SCRVAL,>20,CHRVAL,6,0,>07 EXVDAT BYTE 0,>E0,0,>20,0,6,0,>07 CBVDAT BYTE 0,>E0,0,>0C,0,6,0,>07 EAVDAT BYTE 0,>E0,0,>E,1,6,1,>F5 * * MESSAGE FOR ACCEPT TONE. * BEEPY BYTE 39 TEXT 'HERE IS AN ACCEPT TONE FROM A GPL CALL!' * * MESSAGE FOR BAD RESPONSE TONE. * BEEPN BYTE 44 TEXT 'HERE IS A BAD RESPONSE TONE FROM A GPL CALL!' * * FLOATING POINT REPRESENTATION OF A NUMBER -2,345,600. * EVEN FLOAT BYTE >BC,>FE,>22,>38,0,0,0,0,0 * * MESSAGE FOR THE ABOVE. * FLTMES BYTE 48 TEXT 'THE FOLLOWING NUMBER IS -2345600 ' TEXT 'OR -2.3456E6: ' OPNMSG BYTE 36 TEXT 'OPENING THE FILE RUNDEMO FOR DISPLAY' * * PERIPHIAL ACCESS BLOCK FOR THE FILE. * PABDSC DATA >0014,>0000,>5000,>0000 BYTE 0 BYTE NMELEN NAME TEXT 'DSK1.ERUNDEMO' NMELEN EQU $-NAME * * CAN'T OPEN FILE MESSAGE * CNTOPN BYTE 38 TEXT 'CAN NOT OPEN THE FILE LISTING ABORTED!' * * STORAGE BUFFER FOR DSR INPUT. * DATBUF BSS 84 * * END OF FILE ENCOUNTERED MESSAGE. * EOF BYTE 17 TEXT '** END OF FILE **' * * DEBUGGING MESSAGES. * TRYALC BYTE 39 TEXT 'TRYING TO ALLOCATE VDP RAM FOR THE PAB!' TRYSUC BYTE 21 TEXT 'ALLOCATION SUCCEEDED!' PABMOV BYTE 36 TEXT 'PAB MOVED TO VDP RAM CALLING DSRLNK!' END ----------------------------------------------------------------------------