+InsaneMultitasker Posted November 27, 2016 Share Posted November 27, 2016 I am looking for a routine that will run an Extended BASIC program based on a variable. A few years back I cobbled something together but can not find the disk or image where it was saved. During my 'hunt' I found two routines that come close. The caveat is that I need the program lines left intact in case of an error, so that ON ERROR can recover an report back if the program load fails. Variable and other space should also remain intact to ensure execution continues successfully. This one doesn't work very well if at all. 100 CALL INIT 110 FOR Z=1 TO LEN(A$) :: CALL LOAD(-41+Z,ASC(SEG$(A$,Z,1)),0) :: NEXT Z :: CALL LOAD(-41,LEN(A$)) :: CALL LOAD(-44,4+LEN(A$)) 120 RUN "DSKx.1234567890" This routine works but it destroys the SUBEND in line 32767. I extended the RUN filename reserved space to allow for hard drive paths. 32765 SUB EXEC(A$) :: CALL PEEK(-31952,AC,AD) :: CALL PEEK(AC*256+AD-65534,AC,AD) :: AF=AC*256+AD-65534 :: CALL LOAD(AF,LEN(A$)) 32766 FOR AC=1 TO LEN(A$) :: CALL LOAD(AF+AC,ASC(SEG$(A$,AC,1))) :: NEXT AC :: CALL LOAD(AF+AC,0) 32767 RUN "DSK1.FILENAME011234567890123456789012345678901234567890" :: SUBEND 1 Quote Link to comment Share on other sites More sharing options...
RXB Posted November 27, 2016 Share Posted November 27, 2016 (edited) Nice but a ton of code. RXB has a subroutine that makes RUN look like crap CALL XBPGM("WDS.VOLUME.SUBVOLUME.PROGRAM",2) The 2 at the end does a NEW and CALL FILES(2) before it loads the program. So the result is like you did this: NEW CALL FILES(2) RUN "WDS.VOLUME.SUBVOLUME.PROGRAM" Edited November 27, 2016 by RXB Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted November 27, 2016 Share Posted November 27, 2016 ... This routine works but it destroys the SUBEND in line 32767. I extended the RUN filename reserved space to allow for hard drive paths. 32765 SUB EXEC(A$) :: CALL PEEK(-31952,AC,AD) :: CALL PEEK(AC*256+AD-65534,AC,AD) :: AF=AC*256+AD-65534 :: CALL LOAD(AF,LEN(A$)) 32766 FOR AC=1 TO LEN(A$) :: CALL LOAD(AF+AC,ASC(SEG$(A$,AC,1))) :: NEXT AC :: CALL LOAD(AF+AC,0) 32767 RUN "DSK1.FILENAME011234567890123456789012345678901234567890" :: SUBEND Does SUBEND still get destroyed if it is on a line by itself? ...lee Quote Link to comment Share on other sites More sharing options...
Sinphaltimus Posted November 27, 2016 Share Posted November 27, 2016 I am looking for a routine that will run an Extended BASIC program based on a variable. A few years back I cobbled something together but can not find the disk or image where it was saved. During my 'hunt' I found two routines that come close. The caveat is that I need the program lines left intact in case of an error, so that ON ERROR can recover an report back if the program load fails. Variable and other space should also remain intact to ensure execution continues successfully. This one doesn't work very well if at all. 100 CALL INIT 110 FOR Z=1 TO LEN(A$) :: CALL LOAD(-41+Z,ASC(SEG$(A$,Z,1)),0) :: NEXT Z :: CALL LOAD(-41,LEN(A$)) :: CALL LOAD(-44,4+LEN(A$)) 120 RUN "DSKx.1234567890" This routine works but it destroys the SUBEND in line 32767. I extended the RUN filename reserved space to allow for hard drive paths. 32765 SUB EXEC(A$) :: CALL PEEK(-31952,AC,AD) :: CALL PEEK(AC*256+AD-65534,AC,AD) :: AF=AC*256+AD-65534 :: CALL LOAD(AF,LEN(A$)) 32766 FOR AC=1 TO LEN(A$) :: CALL LOAD(AF+AC,ASC(SEG$(A$,AC,1))) :: NEXT AC :: CALL LOAD(AF+AC,0) 32767 RUN "DSK1.FILENAME011234567890123456789012345678901234567890" :: SUBEND Is that double 1 supposed to be there or a typo? or does it not matter? DSK1.FILENAME011... Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted November 27, 2016 Share Posted November 27, 2016 Is that double 1 supposed to be there or a typo? or does it not matter? DSK1.FILENAME011... The string format is just programmer's bookkeeping. That entire string is a placeholder to allow a device name (“DSK1.”) followed by, at least, a filename of up to 10 characters (“FILENAME01”). The “12345678901 ...” counts off 40 more spaces for hard-disk subdirectories a user might need between the device name and the filename. The whole string could have been 55 spaces or random characters, but it would make it difficult for the programmer (Tim) to read. ...lee Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted November 27, 2016 Author Share Posted November 27, 2016 Does SUBEND still get destroyed if it is on a line by itself? ...lee No, portions of the previous line and/or statements get over-written by the filename and the RUN statement disappears. Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted November 28, 2016 Share Posted November 28, 2016 This should do the trick: 32764 SUB EXEC(A$):: CALL PEEK(-31952,AC,AD):: CALL PEEK(AC*256+AD-65530,AC,AD):: AF=AC*256+AD-65534 :: CALL LOAD(AF,LEN(A$)) 32765 FOR AC=1 TO LEN(A$):: CALL LOAD(AF+AC,ASC(SEG$(A$,AC,1))):: NEXT AC :: CALL LOAD(AF+AC,0) 32766 RUN "DSK1.FILENAME011234567890123456789012345678901234567890" 32767 SUBEND The SUBEND needs to be on a separate line. The CALL LOAD(AF+AC,0) tells XB that it is at the end of the line when it comes to the zero, so the SUBEND is lost. 32766 should only have RUN "DSK1.etc". Also if you change the line numbers, make sure these are the very last line numbers in the program 3 Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted November 28, 2016 Author Share Posted November 28, 2016 This should do the trick: 32764 SUB EXEC(A$):: CALL PEEK(-31952,AC,AD):: CALL PEEK(AC*256+AD-65530,AC,AD):: AF=AC*256+AD-65534 :: CALL LOAD(AF,LEN(A$)) 32765 FOR AC=1 TO LEN(A$):: CALL LOAD(AF+AC,ASC(SEG$(A$,AC,1))):: NEXT AC :: CALL LOAD(AF+AC,0) 32766 RUN "DSK1.FILENAME011234567890123456789012345678901234567890" 32767 SUBEND The SUBEND needs to be on a separate line. The CALL LOAD(AF+AC,0) tells XB that it is at the end of the line when it comes to the zero, so the SUBEND is lost. 32766 should only have RUN "DSK1.etc". Also if you change the line numbers, make sure these are the very last line numbers in the program Yes, this seems to do the trick! When I run this subroutine, the RUN line 32766 changes (as does its length) and the program lines are intact. I see you changed the PEEK offset in line 32764. Is that to account for the extra line 32767 prior to the RUN statement? Also just for completeness, if I wanted to do the same thing without a subprogram, would I change the offset to the original number like this: 32765 CALL PEEK(-31952,AC,AD):: CALL PEEK(AC*256+AD-65534,AC,AD):: AF=AC*256+AD-65534 :: CALL LOAD(AF,LEN(A$)) 32766 FOR AC=1 TO LEN(A$):: CALL LOAD(AF+AC,ASC(SEG$(A$,AC,1))):: NEXT AC :: CALL LOAD(AF+AC,0) 32767 RUN "DSK1.FILENAME01234567890123456789012345678901234567890" (I'm having trouble with ON ERROR but I have run out of time for tonight.) Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted November 28, 2016 Share Posted November 28, 2016 Yes, this seems to do the trick! When I run this subroutine, the RUN line 32766 changes (as does its length) and the program lines are intact. I see you changed the PEEK offset in line 32764. Is that to account for the extra line 32767 prior to the RUN statement? Also just for completeness, if I wanted to do the same thing without a subprogram, would I change the offset to the original number like this: 32765 CALL PEEK(-31952,AC,AD):: CALL PEEK(AC*256+AD-65534,AC,AD):: AF=AC*256+AD-65534 :: CALL LOAD(AF,LEN(A$)) 32766 FOR AC=1 TO LEN(A$):: CALL LOAD(AF+AC,ASC(SEG$(A$,AC,1))):: NEXT AC :: CALL LOAD(AF+AC,0) 32767 RUN "DSK1.FILENAME01234567890123456789012345678901234567890" (I'm having trouble with ON ERROR but I have run out of time for tonight.) Yep, the different PEEK offset is because you want to doctor the second to last line, hence the 4 byte difference. I think the code you show would work if you use ON ERROR line number which should send you back into the program so you can enter a different string. Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted January 8, 2017 Author Share Posted January 8, 2017 Yep, the different PEEK offset is because you want to doctor the second to last line, hence the 4 byte difference. I think the code you show would work if you use ON ERROR line number which should send you back into the program so you can enter a different string. I recently had a chance to try ON ERROR within the EXEC subprogram. 32760 SUB EXEC(A$) 32761 ON ERROR 32762::GOTO 32764 32762 SUBEXIT 32764 CALL PEEK(-31952,AC,AD):: CALL PEEK(AC*256+AD-65530,AC,AD):: AF=AC*256+AD-65534 :: CALL LOAD(AF,LEN(A$)) 32765 FOR AC=1 TO LEN(A$):: CALL LOAD(AF+AC,ASC(SEG$(A$,AC,1))):: NEXT AC :: CALL LOAD(AF+AC,0) 32766 RUN "DSK1.FILENAME011234567890123456789012345678901234567890" 32767 SUBEND If the target file does not exist, an error is generated and XB transfers control to the specified line number. However, XB then halts with an error, "MUST BE IN SUBPROGRAM IN 32762" I suspect the RUN statement does some housecleaning prior to loading the target program. Deleting 32764,32765 and replacing line 32766 with "OPEN #1:"AA"", generates an IO error that is correctly trapped by the ON ERROR handler. I might need to use a hard-coded RUN statement as a fail safe or trust that if the path is correct that the program will load. I do have an assembly-based routine that will check for a file's existence, perhaps I need to pair them together instead of relying upon ON ERROR here. If only TI had allowed a string variable here as they do with the DELETE command. Quote Link to comment Share on other sites More sharing options...
+mizapf Posted January 8, 2017 Share Posted January 8, 2017 Well, yes, just think about RUN A$ with A$="DSK1.SOMEPRG", which was the first proof of 1337-ness back in those days, if you managed to get that running or at least something similar. People came up with lots of wild CALL LOAD hacks for their catalogers. 1 Quote Link to comment Share on other sites More sharing options...
RXB Posted January 9, 2017 Share Posted January 9, 2017 Also something I pointed out in Micropendium (forgot what year) is that these "TRICKS" all ignore it bypasses normal XB start and Random Numbers do not work properly for some programs. There is a way to do this that no one seems to have tried: *********************************************************** * START EXECUTION OF A PROGRAM OR STATEMENT * DATA: * RAM(START) points into line number table at the * first line to execute * @PGMFLG contains >FF if executing a program or zero * if imperative statement *********************************************************** EXEC CZ @PRGFLG If program BS GA0AE DST V@START,@EXTRAM Line to start execution at DINCT @EXTRAM Pointer to text pointer CALL INTRND Initialize random number EXEC1 ST X2,@XPT Initialize screen display BR GA0B2 GA0AE DST CRNBUF,@PGMPTR Executing out of crunch buffe GA0B2 DST EXEC20,@RTNG Address of return from ALC DST NUDTB,@NUDTAB NUD table address for ALC XML EXECG Execute XB EXEC20 CASE @ERRCOD+1 Check type of return BR EXECND 0 - NORMAL END BR EXECBK 1 - BREAKPOINT BR EXECTR 2 - TRACE BR ERORZ 3 - ERROR BR WARNGZ 4 - WARNING BR ONERR 5 - ON ERROR BR UDF 6 - FUNCTION BR ONBRK 7 - ON BREAK BR CONCAT 8 - CONCATENATE STRINGS "&" BR ONWARN 9 - ON WARNING BR GPLCAL A - CALL STATEMENT WARNGZ CH >B0,@SUBSTK BS ERRSO * Stack overflow * ALLOW ROOM ON STACK FOR WARNING CALLS WRNN01 CALL WARNZZ ONLY WARNING MSG FROM XB SUPPORT BYTE 2 * NUMERIC OVERFLOW BR CLRRTN Clear ERRCOD and return * NORMAL END OF EXECUTION EXECND CZ @PRGFLG If imperative mode BR ERRRDY CALL CHRTAB Load the default character se B TOPL15 Return to top-level ERRRDY CALL ERRZZ Display * READY * BYTE 0 * TRACE-MODE turned on - display line number EXECTR CLR @VARW Clear upper address byte ST @XPT,@VARW+1 Get current x-pointer DADD NLNADD-3,@VARW Make a valid screen address DCH NLNADD+22,@VARW If might go off screen BR GA102 XML SCROLL SCROLL to next line DST NLNADD,@VARW Re-initialize screen address GA102 ST LESS+OFFSET,V*VARW Display open bracket "(" DINC @VARW Increment screen address CALL ASC Convert line # into ASCII ST GREAT+OFFSET,V*VARW Display close bracket ")" DSUB NLNADD-4,@VARW Update the x-pointer ST @VARW+1,@XPT CLRRTN DCLR @ERRCOD Clear the return vector XML RTNB Return to ALC * BREAKPOINT OR BREAK-KEY RECIEVED EXECBK CZ @PRGFLG If break or program BS ERRBRK DST @EXTRAM,@FAC8 @FAC8 : Source addr in ERAM DDECT @FAC8 Point to the line # CALL UBSUB1 Reset the breakpoint SCAN Get break key out of queue EXEC6C DST @PGMPTR,V@SPGMPT Save text pointer EXEC6D DST @EXTRAM,V@SEXTRM Save line number table pointe DST @VSPTR,V@SAVEVP Save value stack pointer DST @BUFLEV,V@SBUFLV Save crunch buffer level DST @LSUBP,V@SLSUBP Save last subprogram on stack ST @FLAG,V@SFLAG Save FLAG for continue AND >63,V@SFLAG Only warning and break bits ERRBRK CALL ERRZZ * BREAKPOINT BYTE 1 *********************************************************** * NUD / STATEMENT BRANCH TABLE *********************************************************** NUDTB BR RECX 'RECORD' 0 BR NBREAK 'BREAK' 0 BR NUNBRK 'UNBREAK' 0 BR NTRACE 'TRACE' 0 BR NUNTRC 'UNTRACE' 0 BR NREADX 'READ' 0 BR PRINTX 'PRINT' 0 BR SZRUNX 'RUN' 0 BR LINPUX Reserved for LINPUT 1 BR RESTOX 'RESTORE' 1 BR NRNDMZ 'RANDOMIZE' 1 BR INPUTX 'INPUT' 1 BR OPENX 'OPEN' 1 BR CLOSEX 'CLOSE' 1 BR NPI 'PI' 1 BR NMAX 'MAX' 1 BR NMIN 'MIN' 2 BR RPTZ01 'RPT$' 2 BR ACCEPX 'ACCEPT' 2 BR EOFX 'EOF' 2 BR ASC01 'ASC' 2 BR POS01 'POS' 2 BR VAL01 'VAL' 2 BR STRZ01 'STR$' 2 BR SEGZ01 'SEG$' 3 BR DELETX 'DELETE' 3 BR DISPLX 'DISPLAY' 3 BR LEN01 'LEN' 3 BR CHRZ01 'CHR$' 3 *RXB PATCH CODE FOR BASIC RND REPLACEMENT *********** BR NRND 'RND' 3 * The following are long branches to another GROM EOFX B EOF SZRUNX B SZRUN RECX B REC NREADX B NREAD PRINTX B PRINT RESTOX B RESTOR INPUTX B INPUT OPENX B OPEN CLOSEX B CLOSE ACCEPX B ACCEPT DISPLX B DISPL1 DELETX B DELET LINPUX B LINPUT *********************************************************** * FLAGS USED IN EXECUTION MODE: this needs to be checked * @FLAG BIT RESET SET * 0 * 1 Warning PRINT PRINT off * 2 Warning NEXT STOP * 3 Not in UDF Executing a UDF * 4 TRACE mode Normal mode * 5 * 6 BREAK allowed BREAK not allowed * 7 No LST/EDT protect LIST/EDIT protected *********************************************************** * ON WARNING {NEXT | STOP | PRINT} * ON WARNING NEXT - Causes warning messages to be ignored * and execution to continue as if a * warning never occurred * ON WARNING STOP - Causes a warning to be treated as an * error - i.e. the message is displayed * and execution is halted * ON WARNING PRINT - Causes the default warning handling to * be in effect, i.e. any warning * messages are printed and execution * continues *********************************************************** ONWARN XML PGMCHR GET OPTION CEQ PRINTZ,@CHAT If print BR GA1B7 AND >F9,@FLAG Turn on print and contiue B ONWRN5 GA1B7 CEQ STOPZ,@CHAT BR GA1C4 AND >FD,@FLAG Turn on print OR >04,@FLAG Turn on stop BR ONWRN5 GA1C4 CEQ NEXTZ,@CHAT * SYNTAX ERROR BR ERRSYN OR >02,@FLAG Turn off print AND >FB,@FLAG Turn off stop ONWRN5 XML PGMCHR Check for EOS ONWRN7 CALL CHKEND Error if not EOS BR ERRSYN If not EOS DCLR @ERRCOD XML CONT Continue *********************************************************** * ON ERROR {line number | STOP} * ON ERROR line number - causes the error routine to build * an error stack entry and pass * control to the line specified in * the most-recently executed * on-error-statement * ON ERROR STOP - causes the default error handling * conditions to be in effect. i.e. any * errors that occur cause execution to halt * an a message to be displayed *********************************************************** ONERR XML PGMCHR Get option CEQ LNZ,@CHAT If line # then find the line BR GA20E XML PGMCHR Get upper byte ST @CHAT,@FAC XML PGMCHR Get lower byte ST @CHAT,@FAC1 DST @ENLN,@FAC2 DSUB 3,@FAC2 Pointing to 1st line # * Consider both ERAM and RAM cases to get line # from the * line number table. Also reset the break bit. ONERR2 CALL GRSUB3 Get 2 bytes from either RAM/E BYTE FAC2 * FAC2 has the address DCEQ @EEE1,@FAC If found BS ONERR4 DCH @STLN,@FAC2 Not found BR ERRLNF DSUB 4,@FAC2 Goto next line BR ONERR2 ONERR4 DINCT @FAC2 DST @FAC2,V@ERRLN BR GA216 GA20E CEQ STOPZ,@CHAT * SYNTAX ERROR BR ERRSYN DCLR V@ERRLN Back to default error handlin GA216 BR ONWRN5 Finish up same as ON WARNING *********************************************************** * ON BREAK {NEXT | STOP} * ON BREAK NEXT - Causes any breakpoints which have been * set on statements to be ignored when the * statement is encountered and also masks * the shift-C key so that it is ignored * ON BREAK STOP - Causes the default break handling to be * in force., i.e. execution is halted and * the BREAKPOINT message is displayed on * the screen *********************************************************** ONBRK XML PGMCHR Get next char to find option CEQ STOPZ,@CHAT If stop option specified BR GA225 AND >BF,@FLAG break allowed B GA22D Don't change this to BR GA22D GA225 CEQ NEXTZ,@CHAT If next option number BR ERRSYN specified then syntax error OR >40,@FLAG If next option specified then * break NOT allowed GA22D BR ONWRN5 Finish up same as ON WARNING *********************************************************** * GPLCAL - If a call is made to a subprogram that does not * not exist either in the BASIC program itself or in the * internal GPL subprogram list then one final attempt is * made to find the subprogram at execution time by * searching for the subprogram in the console or a * peripheral. If not found there, then a * *SUBPROGRAM NOT FOUND error occurs * * Input: the subprogram name is in the FAC and the length * of the name is in FAC15 *********************************************************** GPLCAL CZ @RAMFLG Can't try if CPU program BR ERRSNF DSRL 8,@FAC15 Make name length a double DSUB @FAC15,@PGMPTR Point back at name DDEC @PGMPTR Point at name length DST @PGMPTR,@FAC12 Set pointer to name CALL LINK Issue 'Call Program Link' BYTE 10 * Search subprogram lists BR ONWRN7 If all ok, check-end and rtn BR ERRSNF If not found, error *********************************************************** The above code is the GPL XB code for EXEC for run a XB program line out of CRUNCH BUFFER (or line execute buffer like when you type in a line) but if you set the PRGFLG (>8344) to >FF which means PROGRAM mode (>00 is EDIT mode) this routine sets up everything properly and runs the program. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.