DSRLNK & GPLLNK for 99/4A
gregg at okstate.UUCP
gregg at okstate.UUCP
Sun Feb 17 05:37:00 AEST 1985
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 at 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+, at 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, at 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, at PAD(R4)
SWPB R1
MOVB R1, at 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, at 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, at 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
----------------------------------------------------------------------------
More information about the Comp.sources.unix
mailing list