senior_falcon Posted July 30, 2014 Share Posted July 30, 2014 Many of XB's built in subprograms have optional variables. For example, CALL HCHAR(ROW,COL,CHAR[,REPEAT]) where the repeat is optional. Is there any way to have optional variables like this in a user written subprogram? Quote Link to comment Share on other sites More sharing options...
+OLD CS1 Posted July 30, 2014 Share Posted July 30, 2014 I am going to jump on this, and then go check myself. IIRC, In XB you can set up sub-programs which are essentially over-loaded like in C: multiple SUB statements with the same name but different number of parameters. Nope, did not work. I swear I had seen something like this before: 10 CALL TEST(1,2,3) 20 CALL TEST(4,5) 30 END 100 SUB TEST(X,Y) 110 PRINT X,Y 120 SUBEND 200 SUB TEST(X,Y,Z) 210 CALL TEST(X,Y) 220 SUBEND The results should have been to print "1 2" and "4 5", but instead you get * RECURSIVE SUBPROGRAM CALL IN 210 IN TEST CALLED FROM 10. Quote Link to comment Share on other sites More sharing options...
ti99_forever Posted July 30, 2014 Share Posted July 30, 2014 No, but you could pass an array. CALLs are usually to GROM/GPL, which parses the statements for multiple parameters. User-defined are BASIC, and do not support that. Still, they are awesome. Quote Link to comment Share on other sites More sharing options...
RXB Posted July 30, 2014 Share Posted July 30, 2014 Well this is the unmodified code in GPL GROM for XB of the CALL namehere or SUB namehere <0361> COPY 'DSK8.SRXB3-G' <0001> *********************************************************** <0002> * CALLS routine <0003> * This routine scans the CALL statement. Get the subprogram <0004> * name, search the table and update the call list <0005> * (value stack area) if necessary. Share eht same XML <0006> * search routine as the symbol table code uses. <0007> *********************************************************** <0008> 716B 0F,79 CALLS XML PGMCHR Get token after call <0009> 716D 06,71,4F CALL CHKSYN Check subprogram name <0010> 7170 C8 BYTE UNQSTZ * Must start with unquoted stri <0011> 7171 C6,42,0F CH >0F,@CHAT * NAME TOO LONG!! <0012> 7174 76,57 BS NTLERR <0013> 7176 BD,00,2C DST @PGMPTR,@VAR0 Save program pointer to name <0014> 7179 BE,5B,4A ST FAC,@FAC17 Set up a pointer <0015> 717C BC,59,42 ST @CHAT,@FAC15 Save name length <0016> 717F BC,5A,42 ST @CHAT,@FAC16 Save name length as a counter <0017> 7182 0F,79 CALL20 XML PGMCHR Get one byte of name <0018> 7184 BC,90,5B ST @CHAT,*FAC17 Store that character in FAC a 7187 42 <0019> 7188 90,5B INC @FAC17 Increment pointer <0020> 718A 92,5A DEC @FAC16 Decrement conter <0021> 718C 51,82 BR CALL20 Get next character <0022> * Exchange call list address wit <0023> * symbol table address to run th <0024> * same search routine used for <0025> * symbol table search. <0026> 718E C1,0A,3E DEX @SYMTAB,@CALIST <0027> 7191 0F,7D XML SCHSYM Search to see if name there <0028> 7193 C1,3E,0A DEX @CALIST,@SYMTAB Exchange back both addresses <0029> 7196 71,BE BS SCAN67 If name found do nothing <0030> 7198 8E,80,89 CZ @RAMFLG If not imperative and ERAM <0031> 719B 71,AE BS G71AE <0032> 719D 0F,77 XML VPUSH Put first 8 byte of name <0033> 719F BD,00,6E DST @VSPTR,@VAR0 Pointing to new name location <0034> 71A2 CE,59,08 CGT >08,@FAC15 If more characters in name <0035> 71A5 51,AE BR G71AE <0036> 71A7 35,00,08 MOVE 8,@FAC8,@FAC Move rest of the name 71AA 4A,52 <0037> 71AC 0F,77 XML VPUSH Push one more time <0038> 71AE 86,4A G71AE CLR @FAC <0039> 71B0 BC,4B,59 ST @FAC15,@FAC1 Put in name length <0040> 71B3 BD,4C,0A DST @CALIST,@FAC2 Put in call list link <0041> 71B6 BD,4E,00 DST @VAR0,@FAC4 Put in pointer to name <0042> 71B9 0F,77 XML VPUSH Put the entry in the VDP <0043> 71BB BD,0A,6E DST @VSPTR,@CALIST Change pointer to call list <0044> 71BE 0F,79 SCAN67 XML PGMCHR <0045> 71C0 51,3F BR CONSCN <0046> *********************************************************** <0047> * SUBS routine <0048> * This routine scans SUB statement in subprogram. First <0049> * check the subprogram name and call list. Then builds <0050> * subprogram table without argument list, scans symbols in <0051> * the subprogram and create symbol table for the subprogram <0052> * make entry to the subprogram table and add (if necessary) <0053> * to call list. 99/4 GPL-ASSEMBLER (Pass 3) correct PAGE 0046 EDIT-359 <0054> *********************************************************** <0055> 71C2 06,71,42 SUBS CALL IMPIF Can't be imperative or in "IF <0056> 71C5 8E,17 CZ @FORNET Check FOR-NEXT nesting <0057> 71C7 56,6B BR ERRFNN <0058> 71C9 DA,16,01 CLOG >01,@XFLAG Called first time <0059> 71CC 51,D7 BR G71D7 <0060> 71CE DA,16,08 CLOG >08,@XFLAG <0061> 71D1 56,73 BR ERRMS <0062> * Cannot be in subprogram. Can't start another one. <0063> 71D3 BD,A3,92 DST @SYMTAB,V@TABSAV Finish off main table 71D6 3E <0064> * From the second SUB statement <0065> 71D7 87,3E G71D7 DCLR @SYMTAB Start with empty symbol table <0066> 71D9 B6,16,28 OR >28,@XFLAG Set flag for SAFLG and SUBFLG <0067> 71DC B2,16,FE AND >FE,@XFLAG Reset REMODE flag <0068> 71DF 0F,79 XML PGMCHR Get name behind SUB statement <0069> 71E1 06,71,4F CALL CHKSYN Make sure it's unquoted strin <0070> 71E4 C8 BYTE UNQSTZ <0071> 71E5 C6,42,0F CH >0F,@CHAT Length must be <= 15 <0072> 71E8 76,57 BS NTLERR <0073> 71EA BC,4B,42 ST @CHAT,@FAC1 Save name length <0074> 71ED BD,4E,2C DST @PGMPTR,@FAC4 Assume pointer to VDP name <0075> 71F0 8E,80,84 CZ @RAMTOP But if ERAM save name in tabl <0076> 71F3 72,0E BS G720E <0077> 71F5 86,4A CLR @FAC <0078> 71F7 0F,72 XML MEMCHK FAC already has name length <0079> 71F9 76,63 BS ERRMEM * MEMORY FULL <0080> 71FB A5,40,4A DSUB @FAC,@FREPTR Get pointer to put name in <0081> 71FE BD,58,40 DST @FREPTR,@EEE1 Re-do pointer to name <0082> 7201 91,58 DINC @EEE1 Correct for one off <0083> 7203 BD,56,4A DST @FAC,@FFF1 Set for XML GVWITE <0084> 7206 BD,54,2C DST @PGMPTR,@DDD1 Set for XML GVWITE <0085> 7209 0F,8B XML GVWITE Move @FFF1 bytes from ERAM at <0086> * DDD1 to VDP at EEE1 <0087> * <0088> * Start building the subprogram table <0089> 720B BD,4E,58 DST @EEE1,@FAC4 Put pointer in VRAM to name <0090> 720E BF,4A,00 G720E DST 14,@FAC Minimum table size for subpro 7211 0E <0091> 7212 0F,72 XML MEMCHK Make sure enough room there <0092> 7214 76,63 BS ERRMEM * MEMORY FULL <0093> 7216 86,4A CLR @FAC Prepare for name length <0094> 7218 BC,4B,42 ST @CHAT,@FAC1 Get the name length <0095> 721B BD,4C,3A DST @SUBTAB,@FAC2 Save subprogram table address <0096> 721E 87,50 DCLR @FAC6 Mark end of argumant list <0097> * @FAC = name length @FAC2 = subprogram table lin <0098> * @FAC4 = pointer to name @FAC6 = argument list = 00 <0099> * @FAD8 = @PGMPTR @FAC10 = @EXTRAM <0100> * @FAC12 = symbol table = 00 <0101> 7220 A1,2C,4A DADD @FAC,@PGMPTR Skip the name to look ahead <0102> 7223 35,00,04 MOVE 4,@PGMPTR,@FAC8 Copy PGMPTR and EXTRAM 7226 52,2C <0103> 7228 87,56 DCLR @FAC12 Assume subpgm has no symbol t <0104> 722A A7,40,00 DSUB 14,@FREPTR Reset free pointer 722D 0E <0105> 722E BD,3A,40 DST @FREPTR,@SUBTAB Copy <0106> 7231 91,3A DINC @SUBTAB Set new subtable pointer <0107> 7233 35,00,0E MOVE 14,@FAC,V*SUBTAB Put the table in!! 7236 B0,3A,4A <0108> * Start fixing up subprogram's symbol table <0109> 7239 BD,A3,9A DST @SUBTAB,V@SSTEMP Copy address of subtable 723C 3A <0110> 723D A3,A3,9A DADD 6,V@SSTEMP Point to argument list 7240 00,06 99/4 GPL-ASSEMBLER (Pass 3) correct PAGE 0047 EDIT-359 <0111> 7242 BD,A3,9C DST V@SSTEMP,V@SSTMP2 Duplicate for later use 7245 A3,9A <0112> 7247 0F,79 XML PGMCHR Get next token <0113> 7249 06,71,5A CALL CHKEND Check if end of statement <0114> 724C 72,CB BS SCAN90 Yes. Get out here quick <0115> * Start looking at aruguments. <0116> 724E 06,71,4F CALL CHKSYN Check for left parenthesis <0117> 7251 B7 BYTE LPARZ <0118> 7252 B6,16,80 SCAN86 OR >80,@XFLAG Flag for ENTXFL <0119> 7255 06,73,05 CALL ENTERX Enter next parameter <0120> 7258 BF,4A,00 DST 2,@FAC Get room for ptr in sub block 725B 02 <0121> 725C 0F,72 XML MEMCHK See if we had space for 2 byt <0122> 725E 76,63 BS ERRMEM * MEMORY FULL <0123> 7260 BD,4A,A3 DST V@SSTEMP,@FAC Copy current arg list pointer 7263 9A <0124> 7264 A5,4A,3E DSUB @SYMTAB,@FAC Find length from table addres <0125> * Move symbol table down two byt <0126> * to make space for next argueme <0127> FFFE MINUST EQU -2 <0128> 7267 34,4A,EF MOVE @FAC,V*SYMTAB,V@MINUST(@SYMTAB) 726A FF,FE,3E 726D B0,3E <0129> 726F 97,3A DDECT @SUBTAB Adjust the subtable pointer <0130> 7271 97,A3,9C DDECT V@SSTMP2 Adjust to point to first argu <0131> 7274 BD,00,A3 DST V@SSTEMP,@VAR0 7277 9A <0132> 7278 BD,EF,FF DST @SYMTAB,V@MINUST(@VAR0) Put pointer in subtab 727B FE,00,3E <0133> 727E BD,4A,3E DST @SYMTAB,@FAC Copy symbol table address <0134> 7281 97,4A DDECT @FAC Pointing to real s.t. address <0135> 7283 BD,4C,E0 SCAN88 DST V@4(@FAC),@FAC2 Copy pointer to symbol table 7286 04,4A <0136> 7288 93,4C DDEC @FAC2 <0137> 728A C5,4C,3A DCH @SUBTAB,@FAC2 If name moved also <0138> 728D 72,93 BS G7293 <0139> 728F 97,E0,04 DDECT V@4(@FAC) correct for the movement. 7292 4A <0140> 7293 8F,E0,02 G7293 DCZ V@2(@FAC) If more symbol there 7296 4A <0141> 7297 72,A4 BS G72A4 <0142> 7299 97,E0,02 DDECT V@2(@FAC) Adjust the link address also 729C 4A <0143> 729D BD,4A,E0 DST V@2(@FAC),@FAC Point to next s.t. address 72A0 02,4A <0144> 72A2 52,83 BR SCAN88 Check for more s.t. adjustmen <0145> 72A4 BD,4A,A3 G72A4 DST V@SSTMP2,@FAC Restore pointer to first argu 72A7 9C <0146> 72A8 D5,4A,A3 G72A8 DCEQ V@SSTEMP,@FAC Fix all pointers in argument 72AB 9A <0147> 72AC 72,B5 BS G72B5 <0148> 72AE 97,B0,4A DDECT V*FAC Shift address by 2 bytes <0149> 72B1 95,4A DINCT @FAC Go to next argument pointer <0150> 72B3 52,A8 BR G72A8 <0151> 72B5 97,3E G72B5 DDECT @SYMTAB Restore s.t. pointer <0152> 72B7 97,40 DDECT @FREPTR Restore free pointer <0153> * Done with building a subprogram table. <0154> 72B9 D6,42,B6 CEQ RPARZ,@CHAT Next character not ")" ? <0155> 72BC 72,C4 BS G72C4 <0156> 72BE 06,71,4F CALL CHKSYN Must be "," <0157> 72C1 B3 BYTE COMMAZ <0158> 72C2 52,52 BR SCAN86 Ge get more argument <0159> 72C4 0F,79 G72C4 XML PGMCHR Finished... <0160> 72C6 06,71,5A CALL CHKEND Check if end of statement 99/4 GPL-ASSEMBLER (Pass 3) correct PAGE 0048 EDIT-359 <0161> 72C9 51,56 BR ERRSYX If not, error <0162> 72CB B2,16,DF SCAN90 AND >DF,@XFLAG Finished scanning sub argumen <0163> 72CE A3,A3,9A DADD 6,V@SSTEMP Point to location of pointer 72D1 00,06 <0164> * in subtab <0165> 72D3 51,3F BR CONSCN Start scanning subprogram <0166> *********************************************************** <0167> * SUBNDS and SUBXTS <0168> * This routine scans SUBEND and SUBEXIT statement <0169> *********************************************************** <0170> 72D5 06,71,47 SUBNDS CALL IMPILL Can't be imperative <0171> 72D8 DA,16,08 CLOG >08,@XFLAG <0172> 72DB 76,6F BS ERRSNS <0173> ********* MUST BE IN SUBPROGRAM message above ************* <0174> 72DD D6,42,A8 CEQ SUBNDZ,@CHAT <0175> 72E0 52,FB BR G72FB Check for end of statement <0176> 72E2 8E,17 CZ @FORNET Check FOR-NEXT nesting <0177> 72E4 56,6B BR ERRFNN <0178> 72E6 DA,16,01 CLOG >01,@XFLAG <0179> 72E9 56,6F BR ERRSNS <0180> 72EB DA,16,40 CLOG >40,@XFLAG <0181> 72EE 51,56 BR ERRSYX <0182> 72F0 BD,00,A3 DST V@SSTEMP,@VAR0 72F3 9A <0183> 72F4 BD,B0,00 DST @SYMTAB,V*VAR0 72F7 3E <0184> 72F8 B6,16,01 OR >01,@XFLAG <0185> 72FB 50,A4 G72FB BR SCAN22 Check for end of statement Quote Link to comment Share on other sites More sharing options...
+OLD CS1 Posted July 30, 2014 Share Posted July 30, 2014 To a degree, I suppose that since each CALL in a program is static -- that is, the program is likely not self-modifying -- you know for each CALL how many parameters you will be passing, thus the changes would be in the sub-program name itself. That sub-program could CALL the related sub-program with the appropriate variables. In the case of something like HCHAR you could have HCHAR(X,Y,C) and RHCHAR(X,Y,C,R), with RHCHAR calling HCHAR R times. Otherwise, I, too, had thought about using arrays. My concern is that un-DIMed arrays are defaulted to having 10 elements, so you consume a good bit of memory unnecessarily if you are only using a few of those elements. Then there is the question of how to properly iterate through the variable, as uninitialized numeric and string elements will be 0 and "", respectively, so these could not be used as end-of-list markers if you expect to actually make use of these values. Nonetheless, that would mean a single parameter passed to a sub-program can have many values. Quote Link to comment Share on other sites More sharing options...
RXB Posted July 30, 2014 Share Posted July 30, 2014 (edited) How this CALL namehere works with SUB namehere is that a Garbage Collection is done on VDP memory for more memory space to use temporary variables in that SUB. So once the SUBEND or SUBEXIT is used that area of VDP has been cleared for use in the normal program area. Your request would require a set size of memory always to be dedicated to SUB namehere variables and as a unknown would be quite impossible to predict results in only 13K of VDP space. I mean how would you know how much memory is required? And as you create variables how much space would be left for normal execution of programs and variables? And that even ignores the VDP Stack used to keep these routine Variables and how would you know which are which unless you dramatically also increase the VDP stack or duplicate it? This is why the routine crashed as the VDP Stack could not figure out which way to go on the stack as you could very easily overflow the VDP stack and counter. Also the problem of calling a name that call the same name? How the heck can a return be executed? 100 GOSUB 200 110 ..... 200 GOSUB 100 210 ...... 300 GOSUB 100 You can see this is impossible to figure out where to go or return. Now a solution to your problem is make a duplicate routine with a dissimilar name. Like TEST1 and TEST2 and TEST3 Edited July 30, 2014 by RXB Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted July 30, 2014 Share Posted July 30, 2014 (edited) I thought there were some overloading going on somewhere too. Changing line 210 did make a difference, but didn't solve the problem. Looks as if the line 200 declaration overwrites the line 100 one !? Edited July 30, 2014 by sometimes99er Quote Link to comment Share on other sites More sharing options...
RXB Posted July 30, 2014 Share Posted July 30, 2014 I thought there were some overloading going on somewhere too. Changing line 210 did make a difference, but didn't solve the problem. Looks as if the line 200 declaration overwrites the line 100 one !? Yea like I said you can not have the same name or SUB name twice even if you change the number of variables needed. How is the software supposed to tell them apart? How can XB tell CALL HCHAR(row,col,char) from CALL HCHAR(char,repeat) from CALL HCHAR(row,col,char,repeat)? Now in RXB I did modify it to see CALL HCHAR(row,col,char,repeat,row,col,char,repeat,row,col,char) but you have to always include the repeat variable. Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted July 30, 2014 Share Posted July 30, 2014 How is the software supposed to tell them apart? How can XB tell CALL HCHAR(row,col,char) from CALL HCHAR(char,repeat) from CALL HCHAR(row,col,char,repeat)? Well, it's possible in other languages by type and/or number of parameters. Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted July 30, 2014 Share Posted July 30, 2014 (edited) How is the software supposed to tell them apart? How can XB tell CALL HCHAR(row,col,char) from CALL HCHAR(char,repeat) from CALL HCHAR(row,col,char,repeat)? Now in RXB I did modify it to see CALL HCHAR(row,col,char,repeat,row,col,char,repeat,row,col,char) but you have to always include the repeat variable. Ah, you said it yourself. How can XB tell CALL HCHAR(row,col,char) from CALL HCHAR(row,col,char,repeat) ? (as correctly and originally stated) Also keep in mind something a bit more complex and different like CALL LOAD. quote: Format CALL LOAD("access-name" [,address, byte1 [,…], file:field, …] ) Description The LOAD subprogram loads an assembly language object file or direct data into the Memory Expansion for later execution using the LINK statement. The LOAD subprogram can specify one or more files from which to load object data or lists of direct load data, which consists of an address followed by data bytes. The address and data bytes are separated by commas. Direct load data must be separated by file:field, which is a string expression specifying a file from which to load assembly language object code. Flle:field may be a null string when it is used merely to separate direct load data fields. Use of the LOAD subprogram with incorrect values can cause the computer to cease to function and require turning it off and back on. Edited July 30, 2014 by sometimes99er Quote Link to comment Share on other sites More sharing options...
Willsy Posted July 30, 2014 Share Posted July 30, 2014 I guess for HCHAR and LOAD etc the number of parameters are figured out the tokenising stage. When the closing parenthesis is encountered it will look to see how many parameters it has pushed on the parameter stack (and perhaps their types (in the case of LOAD)) and from that it can determine the correct course of action. Name overloading could be supporting by hashing the name of the routine together with the number of parameters: SUB TEST(X,Y) SUB TEST(X,Y,Z) Would produce different hashes, since they have a different number of parameters. However, that would require changes *very* deep down inside the tokeniser. Probably don't want to go there! In there be demons, me thinks! Quote Link to comment Share on other sites More sharing options...
RXB Posted July 30, 2014 Share Posted July 30, 2014 Well, it's possible in other languages by type and/or number of parameters. Well, it's possible in other languages by type and/or number of parameters. Ok here is the issue in a nutshell: In XB or RXB the routine called parse works like this, it parses forward each character, so this would mean that parse would now requires a very long look in advance to parse. Now as a GPL programmer for XB where am I going to get all that extra memory to parse so far forward and back again? I do in a few routines in RXB parse 2 character or more ahead but you guys are saying several comma and variables ahead. CALL HCHAR(row,col,char,REPEAT... Then have to jump back to reload them in the proper place, this would really slow down XB. Instead what I and XB originally has done is required the person writting XB to either use REPEAT or not. And if not then that is the end of the statement. Like normal XB is: 100 CALL HCHAR(row,col,char) or 100 CALL HCHAR(row,col,char,repeat) But in RXB you can do: 100 CALL HCHAR(row,col,char) or 100 CALL HCHAR(row,col,char,repeat,row,col,char) or 100 CALL HCHAR(row,col,char,repeat,row,col,char,repeat) And this works in RXB for CHAR, COINC, COLOR, DISTANCE, GCHAR, HCHAR, JOYSTY, KEY, MOTION, and VCHAR. None of these in normal XB are auto-repeating commands as they all require a single line like in normal XB: 100 CALL JOYST(1,X1,Y1) :: CALL JOYSTICK(2,X2,Y2) In RXB you can do this: 100 CALL JOYSTICK(1,X1,Y1,2,X2,Y2) So anyway the source code for XB in in RXB and if you want see what you can do. Quote Link to comment Share on other sites More sharing options...
RXB Posted July 30, 2014 Share Posted July 30, 2014 I guess for HCHAR and LOAD etc the number of parameters are figured out the tokenising stage. When the closing parenthesis is encountered it will look to see how many parameters it has pushed on the parameter stack (and perhaps their types (in the case of LOAD)) and from that it can determine the correct course of action. Name overloading could be supporting by hashing the name of the routine together with the number of parameters: SUB TEST(X,Y) SUB TEST(X,Y,Z) Would produce different hashes, since they have a different number of parameters. However, that would require changes *very* deep down inside the tokeniser. Probably don't want to go there! In there be demons, me thinks! You are correct. The Assembly ROMs in XB take care of most of this and I would like to fix this, but would require a vast amount of time to debug fully for a single person. Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted July 30, 2014 Share Posted July 30, 2014 (edited) Edit: Redundant. Edited August 2, 2014 by sometimes99er Quote Link to comment Share on other sites More sharing options...
Willsy Posted July 30, 2014 Share Posted July 30, 2014 I do in a few routines in RXB parse 2 character or more ahead but you guys are saying several comma and variables ahead. CALL HCHAR(row,col,char,REPEAT... Then have to jump back to reload them in the proper place, this would really slow down XB. That's what stacks are for When you get a number out of the stream, you push it onto the stack. In the case of hchar, numbers are delimited by only two things: a comma, or a closed parenthesis. When you've determined that you've hit the closed parenthesis, you're done parsing. You check the stack depth. If there are <3 or >4 parameters on the stack, then it's a syntax error, otherwise it's legal. It's probably done something like this deep down in the XB interpreter. Of course, it's more complex than that because a parameter might be supplied in the form of an expression, but even then, that expression will eventually yield a numeric value that gets pushed onto the stack. It's certainly not trivial. Interesting, but not trivial. I think BASIC interpreters are complex beasts. Quote Link to comment Share on other sites More sharing options...
RXB Posted July 31, 2014 Share Posted July 31, 2014 That's what stacks are for When you get a number out of the stream, you push it onto the stack. In the case of hchar, numbers are delimited by only two things: a comma, or a closed parenthesis. When you've determined that you've hit the closed parenthesis, you're done parsing. You check the stack depth. If there are <3 or >4 parameters on the stack, then it's a syntax error, otherwise it's legal. It's probably done something like this deep down in the XB interpreter. Of course, it's more complex than that because a parameter might be supplied in the form of an expression, but even then, that expression will eventually yield a numeric value that gets pushed onto the stack. It's certainly not trivial. Interesting, but not trivial. I think BASIC interpreters are complex beasts. A lot of stuff is kept in the VDP stack and this would just slow down XB considerably. A perfect example is CALL LINK is really slow as the amount of house keeping it does for VDP Stack and checking is pretty intense: 99/4 GPL-ASSEMBLER (Pass 3) correct PAGE 0020 EQUATES ALCS-359 <0061> *********************************************************** <0062> * LINK INSTRUCTION : SE Sep 1980 <0063> *********************************************************** <0064> * FORMAT: <0065> * CALL LINK("file-name",parameter1,parameter2,...) <0066> * <0067> * LINK ROUTINE READS THE FILE NAME SPECIFIED BY THE USER A <0068> * SAVE THE ADDRESS OF THE NAME FOR LATER USE. THE FILE WIL <0069> * BE SEARCHED IN UTILITY CODE LATER ON. <0070> * <0071> * PARAMETERS ARE PASSED EITHER BY REFERENCE OR BY VALUE. <0072> * NUMERIC OR STRING VARIABLES AND NUMERIC OR STRING ARRAYS <0073> * ARE PASSED BY REFERENCE AND ALL OTHERS INCLUDING A USER <0074> * DEFINED FUNCTION ARE PASSED BY VALUE. <0075> * <0076> * PARAMETER INFORMATION IS STORED IN CPU >8300 THROUGH >83 <0077> * THAT GIVES A PARAMETER TYPE CODE OF EACH PARAMETER. <0078> * CODE 0 ... Numeric expression <0079> * CODE 1 ... String experession <0080> * CODE 2 ... Numeric variable <0081> * CODE 3 ... String variable <0082> * CODE 4 ... Numeric array <0083> * CODE 5 ... String array <0084> * <0085> * IF A PARAMETER IS PASSED AS A NUMERIC EXPRESSION ITSL <0086> * ACTUAL VALUE GETS PUSHED INTO THE VALUE STACK. IN CASE O <0087> * A STRING EXPRESSION , ITS VALUE STACK CONTAINS AN ID(>65 <0088> * POINTER TO THE VALUE SPACE AND ITS LENGTH. IF A PARAMETE <0089> * GETS PASSED AS A REFERENCE THE PRODUCT OF XML SYM AND XM <0090> * SMB IN THE @FAC AREA GETS PUSHED INTO STACK. <0091> * <0092> * AFTER AN ASSEMBLY LANGUAGE SUBPROGRAM IS EXECUTED LINK <0093> * ROUTINE WILL POP THE STACK TO GET RID OF PARAMETER <0094> * INFORMATION. CONTROL WILL BE TRANSFERED TO THE XB MAIN <0095> * PROGRAM AFTERWARDS. <0096> * <0097> *********************************************************** <0098> * CALL LINK program <0099> *********************************************************** <0100> C325 06,C1,EB LINKIT CALL CHKIN Check if INIT has been called <0101> C328 BD,10,6E DST @VSPTR,@OLDS Save VSPTR for later use <0102> C32B D6,42,B7 CEQ LPARZ,@CHAT Check for "(" <0103> C32E 45,33 BR ERRSYN <0104> C330 0F,79 XML PGMCHR Advance program pointer <0105> C332 0F,74 XML PARSE Get the routine name. <0106> C334 B6 BYTE RPARZ * Read up to ")" <0107> C335 D6,4C,65 CEQ >65,@FAC2 Should be a string <0108> C338 45,9A BR ERRBA <0109> C33A 8F,50 DCZ @FAC6 Don't accept null string <0110> C33C 65,9A BS ERRBA <0111> C33E C6,51,06 CH 6,@FAC7 Should be less then 6 char <0112> C341 65,9A BS ERRBA <0113> C343 0F,77 XML VPUSH Push to make it semi-permanen <0114> C345 86,12 CLR @COUNT Initialize parameter counter <0115> *********************************************************** <0116> * PARAMETERS get evaluated here <0117> *********************************************************** <0118> C347 D6,42,B6 PAR01 CEQ RPARZ,@CHAT No arg. So execute it <0119> C34A 64,05 BS EXE01 <0120> C34C D6,42,B3 CEQ COMMAZ,@CHAT Should have a comma <0121> C34F 45,33 BR ERRSYN <0122> C351 BD,22,2C DST @PGMPTR,@ERRCOD Save text pointer <0123> C354 0F,79 XML PGMCHR Get the character <0124> C356 CA,42,80 CHE >80,@CHAT Must be an expression 99/4 GPL-ASSEMBLER (Pass 3) correct PAGE 0021 EQUATES ALCS-359 <0125> C359 63,C7 BS VAL01 <0126> * If CHAT = LPARZ then pass by expression <0127> C35B 06,C4,2C CALL CLRFAC Clear FAC entry for SYM <0128> C35E 0F,7A XML SYM Read in the symbol table info <0129> * After XML SYM @FAC area contains a pointer to symbo table <0130> * Below statement checks if it is a UDF. <0131> C360 DA,B0,4A CLOG >40,V*FAC Pass by value C363 40 <0132> C364 43,C7 BR VAL01 <0133> C366 D6,42,B3 CEQ COMMAZ,@CHAT Pass by reference <0134> C369 63,E5 BS REF01 <0135> C36B D6,42,B6 CEQ RPARZ,@CHAT Pass by reference <0136> C36E 63,E5 BS REF01 <0137> C370 D6,42,B7 CEQ LPARZ,@CHAT An array <0138> C373 63,7C BS ARRAY <0139> C375 CA,42,80 CHE >80,@CHAT Pass by value <0140> C378 63,C7 BS VAL01 <0141> C37A 45,33 BR ERRSYN <0142> *********************************************************** <0143> * ARRAY case gets checked here <0144> *********************************************************** <0145> * Should look like A(,,) etc. <0146> * Stack entry for an array will look like <0147> * +--------------+-------+---+-------------+--------------- <0148> * | Pointer to | >00 | | Pointer to | <0149> * | symbol table | or | | dim info in | <0150> * | entry | >65 | | real v.s. | <0151> * +- FAC --------+ FAC2 -+---+- FAC4 ------+- FAC6 -------- <0152> * <0153> C37C 0F,79 ARRAY XML PGMCHR Get the next character <0154> C37E D6,42,B6 CEQ RPARZ,@CHAT Pass by reference <0155> C381 63,8F BS ARRAY2 <0156> C383 D6,42,B3 CEQ COMMAZ,@CHAT More array information <0157> C386 63,7C BS ARRAY <0158> C388 93,2C DDEC @PGMPTR Adjust the pointer <0159> C38A BE,42,B7 ST LPARZ,@CHAT <0160> C38D 43,E5 BR REF01 Pass by reference <0161> * In array cases the symbol table address gets stored at FA <0162> * area, and the pointer to the value space (dimension info) <0163> * goes into FAC4 <0164> C38F 0F,79 ARRAY2 XML PGMCHR Advance the program pointer <0165> C391 DA,B0,4A CLOG >80,V*FAC Test string bit C394 80 <0166> C395 43,9D BR GC39D <0167> C397 BE,90,12 ST 4,*COUNT Numeric array C39A 04 <0168> C39B 43,A1 BR GC3A1 <0169> C39D BE,90,12 GC39D ST 5,*COUNT String array case C3A0 05 <0170> * Check if array is being shared. If it is then go back <0171> * through the linkage to get the actuals symbol table <0172> * pointer. Put the pointer to the value space (dimension in <0173> * into FAC4. <0174> C3A1 DA,B0,4A GC3A1 CLOG >20,V*FAC Shared array? C3A4 20 <0175> C3A5 63,BE BS GC3BE <0176> C3A7 35,00,02 MOVE 2,V@6(@FAC),@FAC4 If so, get pointer C3AA 4E,E0,06 C3AD 4A <0177> C3AE DA,EF,FF CLOG >20,V@-6(@FAC4) Shared also? C3B1 FA,4E,20 <0178> C3B4 63,BC BS GC3BC <0179> C3B6 35,00,02 MOVE 2,V*FAC4,@FAC4 Array is not shared C3B9 4E,B0,4E 99/4 GPL-ASSEMBLER (Pass 3) correct PAGE 0022 EQUATES ALCS-359 <0180> C3BC 43,C5 GC3BC BR GC3C5 <0181> C3BE BD,4E,4A GC3BE DST @FAC,@FAC4 Array is not shared <0182> C3C1 A3,4E,00 DADD 6,@FAC4 Point to value space C3C4 06 <0183> C3C5 43,FA GC3C5 BR PUSH <0184> *********************************************************** <0185> * VALUE <0186> * Passing the parameter by value <0187> *********************************************************** <0188> C3C7 BD,2C,22 VAL01 DST @ERRCOD,@PGMPTR Restore program pointer <0189> C3CA 0F,79 XML PGMCHR Skip the first character <0190> C3CC BD,16,0C DST @BYTES,@TEMP In case of passing a string <0191> C3CF 0F,74 XML PARSE Parsing up to comma <0192> C3D1 B6 BYTE RPARZ <0193> C3D2 BD,0C,16 DST @TEMP,@BYTES Restore the value in >0C area <0194> * After parsing @FAC area contains its actual numeric value <0195> * in a numeric case, and the following information in a <0196> * string case. <0197> * +----------------+-----+--+------------+----------------- <0198> * | >001C or | >65 | | Pointer to | Length of string <0199> * | value pointer | | | string | string <0200> * | address | | | | <0201> * +- FAC ----------+-FAC2+--+-FAC4 ------+- FAC6 ---------- <0202> * <0203> C3D5 CE,4C,63 CGT >63,@FAC2 If more then 99 then <0204> C3D8 43,E0 BR GC3E0 <0205> C3DA BE,90,12 ST 1,*COUNT Store flag for string express C3DD 01 <0206> C3DE 43,E3 BR GC3E3 <0207> C3E0 86,90,12 GC3E0 CLR *COUNT Otherwise it is a numeric exp <0208> C3E3 43,FA GC3E3 BR PUSH Push into stack <0209> *********************************************************** <0210> * REFERENCE <0211> * Passing the parameter by reference <0212> *********************************************************** <0213> * Variables, array element and whole array passing. <0214> * <0215> * After SMB @FAC entry shold look like; <0216> * +--------------+------+-----+-------------+-------------- <0217> * | Pointer to | >00 | | Pointer to | <0218> * | symbol table | | | value space | <0219> * | entry | | | | <0220> * +-- FAC -------+ FAC2 +-----+- FAC4 ------+- FAC6 ------- <0221> * for numeric case, and <0222> * +--------------+------+-----+-------------+-------------- <0223> * | Pointer to | >65 | | Pointer to | String <0224> * | value space | | | string | length <0225> * | entry | | | | <0226> * +- FAC --------+ FAC2 +-----+- FAC4 ------+- FAC6 ------- <0227> * for a string case. <0228> C3E5 0F,7B REF01 XML SMB Get the location <0229> C3E7 CA,42,B8 CHE >B8,@CHAT Pass array expression <0230> C3EA 63,C7 BS VAL01 <0231> C3EC 8E,4C CZ @FAC2 <0232> C3EE 43,F6 BR GC3F6 <0233> C3F0 BE,90,12 ST 2,*COUNT Must be a numeric variable C3F3 02 <0234> C3F4 43,FA BR PUSH <0235> C3F6 BE,90,12 GC3F6 ST 3,*COUNT Must be a string variable C3F9 03 <0236> *********************************************************** <0237> * PUSH routine <0238> * Pushes @FAC entry into a value stack. <0239> *********************************************************** 99/4 GPL-ASSEMBLER (Pass 3) correct PAGE 0023 EQUATES ALCS-359 <0240> C3FA 90,12 PUSH INC @COUNT <0241> C3FC CE,12,10 CGT 16,@COUNT Too many parameters <0242> C3FF 65,9A BS ERRBA <0243> C401 0F,77 XML VPUSH <0244> C403 43,47 BR PAR01 Get the next argument. <0245> *********************************************************** <0246> * EXECUTE routine <0247> * Restore file name info transfer control over to ALC <0248> *********************************************************** <0249> C405 BE,4A,20 EXE01 ST >20,@FAC Store blank in the FAC area. <0250> C408 35,00,05 MOVE 5,@FAC,@FAC1 C40B 4B,4A <0251> C40D 35,00,04 MOVE 4,V@12(@OLDS),@STORE Get the file name info C410 14,E0,0C C413 10 <0252> C414 34,16,4A MOVE @STORE+2,V*STORE,@FAC Move to FAC C417 B0,14 <0253> C419 87,22 DCLR @ERRCOD Clear program pointer for <0254> * error code <0255> C41B 0F,20 XML ALSUP Go to CPU at >2000 to execute <0256> C41D 64,C9 BS ERROR Error found <0257> * If no error, start checking s <0258> *********************************************************** <0259> * RETURN to the XB main program. <0260> *********************************************************** <0261> C41F C5,6E,10 NOERR DCH @OLDS,@VSPTR Pop the stack <0262> C422 44,29 BR GC429 <0263> C424 0F,78 XML VPOP Pop the stack <0264> C426 05,C4,1F B NOERR <0265> C429 05,A0,1C GC429 B LNKRTN Check ")" and end of statemen <0266> *********************************************************** <0267> * SUBROUTINES used in this file. <0268> *********************************************************** <0269> C42C 86,4A CLRFAC CLR @FAC <0270> C42E 35,00,07 MOVE 7,@FAC,@FAC1 C431 4B,4A <0271> C433 00 RTN <0272> *********************************************************** CALL LOAD is much more complicated and uses many of the same routines. In RXB I invented a command CALL EXECUTE(RAM-address) This command in RXB is 5 times faster then CALL LINK and using CALL LOAD or CALL PEEK values is faster then CALL LINK. Most of the problem is the number of VDP Stack routines needed. Any repeated house keeping routines are going to slow down XB. Quote Link to comment Share on other sites More sharing options...
+OLD CS1 Posted July 31, 2014 Share Posted July 31, 2014 Hey, Rich... how difficult is it to implement PEEK()? It is cumbersome and slow to have to CALL PEEK() into a variable when you just need the value temporarily. For instance: CALL PEEK(32768,A) :: PRINT 5*A PRINT 5*PEEK(32768) CALL PEEK(32769,B) :: IF B=16 THEN 110 IF PEEK(32769)=16 THEN 110 The second implementation of both above is at least just more neat, but I also expect to be faster and consume less space. Also, a function like VPEEK() would be nice. Quote Link to comment Share on other sites More sharing options...
RXB Posted July 31, 2014 Share Posted July 31, 2014 (edited) Hey, Rich... how difficult is it to implement PEEK()? It is cumbersome and slow to have to CALL PEEK() into a variable when you just need the value temporarily. For instance: CALL PEEK(32768,A) :: PRINT 5*A PRINT 5*PEEK(32768) CALL PEEK(32769,B) :: IF B=16 THEN 110 IF PEEK(32769)=16 THEN 110The second implementation of both above is at least just more neat, but I also expect to be faster and consume less space. Also, a function like VPEEK() would be nice. In order to put something like that into XB requires you put it in the Token Table: 0346] *********************************************************** [0347] * BASIC TOKEN TABLE [0348] * EQU >80 spare token [0349] 0081 ELSEZ EQU >81 ELSE [0350] 0082 SSEPZ EQU >82 :: [0351] 0083 TREMZ EQU >83 $ [0352] 0084 IFZ EQU >84 IF [0353] 0085 GOZ EQU >85 GO [0354] 0086 GOTOZ EQU >86 GOTO [0355] 0087 GOSUBZ EQU >87 GOSUB [0356] 0088 RETURZ EQU >88 RETURN [0357] 0089 DEFZ EQU >89 DEF [0358] 008A DIMZ EQU >8A DIM [0359] 008B ENDZ EQU >8B END [0360] 008C FORZ EQU >8C FOR [0361] 008D LETZ EQU >8D LET [0362] 008E BREAKZ EQU >8E BREAK [0363] 008F UNBREZ EQU >8F UNBREAK [0364] 0090 TRACEZ EQU >90 TRACE [0365] 0091 UNTRAZ EQU >91 UNTRACE [0366] 0092 INPUTZ EQU >92 INPUT [0367] 0093 DATAZ EQU >93 DATA [0368] 0094 RESTOZ EQU >94 RESTORE [0369] 0095 RANDOZ EQU >95 RANDOMIZE [0370] 0096 NEXTZ EQU >96 NEXT [0371] 0097 READZ EQU >97 READ [0372] 0098 STOPZ EQU >98 STOP [0373] 0099 DELETZ EQU >99 DELETE [0374] 009A REMZ EQU >9A REM [0375] 009B ONZ EQU >9B ON [0376] 009C PRINTZ EQU >9C PRINT [0377] 009D CALLZ EQU >9D CALL [0378] 009E OPTIOZ EQU >9E OPTION [0379] 009F OPENZ EQU >9F OPEN [0380] 00A0 CLOSEZ EQU >A0 CLOSE [0381] 00A1 SUBZ EQU >A1 SUB [0382] 00A2 DISPLZ EQU >A2 DISPLAY [0383] 00A3 IMAGEZ EQU >A3 IMAGE [0384] 00A4 ACCEPZ EQU >A4 ACCEPT [0385] 00A5 ERRORZ EQU >A5 ERROR 99/4 GPL-ASSEMBLER (Pass 3) correct PAGE 0007 EQUATES FLMGR-359 [0386] 00A6 WARNZ EQU >A6 WARNING [0387] 00A7 SUBXTZ EQU >A7 SUBEXIT [0388] 00A8 SUBNDZ EQU >A8 SUBEND [0389] 00A9 RUNZ EQU >A9 RUN [0390] 00AA LINPUZ EQU >AA LINPUT [0391] * EQU >AB spare token (LIBRARY) [0392] * EQU >AC spare token (REAL) [0393] * EQU >AD spare token (INTEGER) [0394] * EQU >AE spare token (SCRATCH) [0395] * EQU >AF spare token [0396] 00B0 THENZ EQU >B0 THEN [0397] 00B1 TOZ EQU >B1 TO [0398] 00B2 STEPZ EQU >B2 STEP [0399] 00B3 COMMAZ EQU >B3 , [0400] 00B4 SEMICZ EQU >B4 ; [0401] 00B5 COLONZ EQU >B5 : [0402] 00B6 RPARZ EQU >B6 ) [0403] 00B7 LPARZ EQU >B7 ( [0404] 00B8 CONCZ EQU >B8 & (CONCATENATE) [0405] * EQU >B9 spare token [0406] 00BA ORZ EQU >BA OR [0407] 00BB ANDZ EQU >BB AND [0408] 00BC XORZ EQU >BC XOR [0409] 00BD NOTZ EQU >BD NOT [0410] 00BE EQUALZ EQU >BE = [0411] 00BF LESSZ EQU >BF < [0412] 00C0 GREATZ EQU >C0 > [0413] 00C1 PLUSZ EQU >C1 + [0414] 00C2 MINUSZ EQU >C2 - [0415] 00C3 MULTZ EQU >C3 * [0416] 00C4 DIVIZ EQU >C4 / [0417] 00C5 CIRCUZ EQU >C5 ^ [0418] * EQU >C6 spare token [0419] 00C7 STRINZ EQU >C7 QUOTED STRING [0420] 00C8 UNQSTZ EQU >C8 UNQUOTED STRING [0421] 00C8 NUMZ EQU >C8 ALSO NUMERICAL STRING [0422] 00C8 NUMCOZ EQU >C8 ALSO UNQUOTED STRING [0423] 00C9 LNZ EQU >C9 LINE NUMBER CONSTANT [0424] * EQU >CA spare token [0425] 00CB ABSZ EQU >CB ABS [0426] 00CC ATNZ EQU >CC ATN [0427] 00CD COSZ EQU >CD COS [0428] 00CE EXPZZ EQU >CE EXP [0429] 00CF INTZ EQU >CF INT [0430] 00D0 LOGZ EQU >D0 LOG [0431] 00D1 SGNZZ EQU >D1 SGN [0432] 00D2 SINZ EQU >D2 SIN [0433] 00D3 SQRZ EQU >D3 SQR [0434] 00D4 TANZ EQU >D4 TAN [0435] 00D5 LENZ EQU >D5 LEN [0436] 00D6 CHRZZ EQU >D6 CHR$ [0437] 00D7 RNDZ EQU >D7 RND [0438] 00D8 SEGZZ EQU >D8 SEG$ [0439] 00D9 POSZ EQU >D9 POS [0440] 00DA VAL EQU >DA VAL [0441] 00DB STRZZ EQU >DB STR$ [0442] 00DC ASCZ EQU >DC ASC [0443] 00DD PIZ EQU >DD PI [0444] 00DE RECZ EQU >DE REC [0445] 00DF MAXZ EQU >DF MAX [0446] 00E0 MINZ EQU >E0 MIN [0447] 00E1 RPTZZ EQU >E1 RPT$ [0448] * EQU >E2 unused [0449] * EQU >E2 unused 99/4 GPL-ASSEMBLER (Pass 3) correct PAGE 0008 EQUATES FLMGR-359 [0450] * EQU >E3 unused [0451] * EQU >E4 unused [0452] * EQU >E5 unused [0453] * EQU >E6 unused [0454] * EQU >E7 unused [0455] 00E8 NUMERZ EQU >E8 NUMERIC [0456] 00E9 DIGITZ EQU >E9 DIGIT [0457] 00EA UALPHZ EQU >EA UALPHA [0458] 00EB SIZEZ EQU >EB SIZE [0459] 00EC ALLZ EQU >EC ALL [0460] 00ED USINGZ EQU >ED USING [0461] 00EE BEEPZ EQU >EE BEEP [0462] 00EF ERASEZ EQU >EF ERASE [0463] 00F0 ATZ EQU >F0 AT [0464] 00F1 BASEZ EQU >F1 BASE [0465] * EQU >F2 spare token (TEMPORARY) [0466] 00F3 VARIAZ EQU >F3 VARIABLE [0467] 00F4 RELATZ EQU >F4 RELATIVE [0468] 00F5 INTERZ EQU >F5 INTERNAL [0469] 00F6 SEQUEZ EQU >F6 SEQUENTIAL [0470] 00F7 OUTPUZ EQU >F7 OUTPUT [0471] 00F8 UPDATZ EQU >F8 UPDATE [0472] 00F9 APPENZ EQU >F9 APPEND [0473] 00FA FIXEDZ EQU >FA FIXED [0474] 00FB PERMAZ EQU >FB PERMANENT [0475] 00FC TABZ EQU >FC TAB [0476] 00FD NUMBEZ EQU >FD # [0477] 00FE VALIDZ EQU >FE VALIDATE [0478] * EQU >FF ILLEGAL VALUE [0479] *********************************************************** [0480] COPY 'DSK8.SRXB4-B' There are a few spaces open but as you can see very few and they require you rewrite the ROMs also so they can be accessed. I am presently working on a Integer RND function called IRND(minimum value,maximum value) that works like this. 100 ON IRND(1,7) GOSUB 200,300,400,500,600,700,800 It uses integer only random numbers so is much faster then the normal XB RND routine and also allows a minimum and maxim value. The reason it is faster is if you look at the XB code for RND you can see why it is so freaking slow compared to BASIC RND function. The XB verison does Vstack pop and push and FMUL and FADD and whole bunch of other crap. The TI BASIC version is so much faster. In answer yea I could but like I showed you PEEK has a low priority compared to more needed things like a faster RND. P.S. RXB has CALL PEEKV and CALL PEEKG also CALL POKEV and CALL POKEG Edited July 31, 2014 by RXB Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted August 2, 2014 Author Share Posted August 2, 2014 My original question was not just idle curiosity. I'll describe why I was interested and throw out an idea out in case someone wants to do something with it. One of the programs included in XB256 is a sound list compiler. This takes CALL SOUNDs and turns them into an assembly language sound list compatible with the sound list player in XB256 and also Matt Haggarty's sound list player. This works fine but one of its drawbacks is that the arguments can only be numbers. There is a large amount of BASIC/XB music existing for the TI that use mathematical expressions in the CALL SOUND statements. My idea was to write an XB subroutine called SLIST (or something similar) that starts at line 30000 and merge it into an XB music program. Then use Classic 99's clipboard to transfer the XB program to a text editor. Replace every CALL SOUND with CALL SLIST, then rewrite the program with "Paste XB". Now when the XB program runs it will go to SLIST instead of doing a CALL SOUND. SLIST was to take the variables passed, put together a sound list for that particular CALL SOUND and save it to disk. Unfortunately, while CALL SOUND can cope with 3 to 9 variables, we learned above that a user written subroutine expects a fixed number of variables to be passed. I can't see any way to to get around this that isn't very cumbersome. However, it could be done with an assembly language subroutine. An A/L sub can look to see how many variables were passed and with that information know how to put together the numbers to make up the sound list. Let's say the A/L sub is called "SOUND". Use a text editor to change CALL SOUND( into CALL LINK("SOUND", Then when the program runs, it goes to the assembly language SOUND, passing the same values that would have gone to the XB CALL SOUND. The A/L SOUND creates a sound list for each CALL SOUND as it is played and writes it to disk. Quote Link to comment Share on other sites More sharing options...
RXB Posted August 2, 2014 Share Posted August 2, 2014 (edited) My original question was not just idle curiosity. I'll describe why I was interested and throw out an idea out in case someone wants to do something with it. One of the programs included in XB256 is a sound list compiler. This takes CALL SOUNDs and turns them into an assembly language sound list compatible with the sound list player in XB256 and also Matt Haggarty's sound list player. This works fine but one of its drawbacks is that the arguments can only be numbers. There is a large amount of BASIC/XB music existing for the TI that use mathematical expressions in the CALL SOUND statements. My idea was to write an XB subroutine called SLIST (or something similar) that starts at line 30000 and merge it into an XB music program. Then use Classic 99's clipboard to transfer the XB program to a text editor. Replace every CALL SOUND with CALL SLIST, then rewrite the program with "Paste XB". Now when the XB program runs it will go to SLIST instead of doing a CALL SOUND. SLIST was to take the variables passed, put together a sound list for that particular CALL SOUND and save it to disk. Unfortunately, while CALL SOUND can cope with 3 to 9 variables, we learned above that a user written subroutine expects a fixed number of variables to be passed. I can't see any way to to get around this that isn't very cumbersome. However, it could be done with an assembly language subroutine. An A/L sub can look to see how many variables were passed and with that information know how to put together the numbers to make up the sound list. Let's say the A/L sub is called "SOUND". Use a text editor to change CALL SOUND( into CALL LINK("SOUND", Then when the program runs, it goes to the assembly language SOUND, passing the same values that would have gone to the XB CALL SOUND. The A/L SOUND creates a sound list for each CALL SOUND as it is played and writes it to disk. This is already built into RXB: 10 ! RXB EXAMPLE CALL IO CHIMES (SOUND LIST) 100 A=8191 110 DATA 5,159,191,223,255,227,1 120 DATA 9,142,1,164,2,197,1,144,182,211,6 130 DATA 3,145,183,212,5 140 DATA 3,146,184,213,4 150 DATA 5,167,4,147,176,214,5 160 DATA 3,148,177,215,6 170 DATA 3,149,178,216,7 180 DATA 5,202,2,150,179,208,6 190 DATA 3,151,180,209,5 200 DATA 3,152,181,210,4 210 DATA 5,133,3,144,182,211,5 220 DATA 3,145,183,212,6 230 DATA 3,146,184,213,7 240 DATA 5,164,2,147,176,214,6 250 DATA 3,148,177,215,5 260 DATA 3,149,178,216,4 270 DATA 5,197,1,150,179,208,5 280 DATA 3,151,180,209,6 290 DATA 3,152,181,210,7 300 DATA 3,159,191,223,0 310 A=A+1 :: READ B :: CALL POKEV(A,B) 320 IF B=0 THEN 330 ELSE 310 330 CALL IO(1,8192) 340 PRINT "CHIMES": :"TYPE:":"CALL IO(1,8192)" Or 100 CALL CLEAR ! CRASH 110 DATA 2,228,242,5 120 DATA 2,228,240,18 130 DATA 2,228,241,16 140 DATA 2,228,242,14 150 DATA 2,228,243,12 160 DATA 2,228,244,10 170 DATA 2,229,245,9 180 DATA 2,229,246,8 190 DATA 2,229,247,7 200 DATA 2,229,248,6 210 DATA 2,229,249,5 220 DATA 2,230,250,4 230 DATA 2,230,251,3 240 DATA 2,230,252,2 250 DATA 2,230,253,1 260 DATA 2,230,254,1 270 DATA 1,255,0,0 280 FOR AD=4096 TO 4160 STEP 4 290 READ V1,V2,V3,V4 300 CALL POKEV(AD,V1,V2,V3,V4) 310 NEXT AD 320 CALL IO(1,4096) 330 PRINT "CRASH": :"TYPE:":"CALL IO(1,4096)" Of course you can use a RXB CALL BLOAD("pathname") :: CALL MOVES("RV",size,to,from) as that would be faster to load. So using CALL BLOAD is your loader your asked for and CALL MOVES puts that list in the location you want. Thus CALL BSAVE would save the file to disk and CALL MOVES would put that list there for you there before the save. Edited August 2, 2014 by RXB Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted August 2, 2014 Share Posted August 2, 2014 (edited) My original question was not just idle curiosity. I'll describe why I was interested and throw out an idea out in case someone wants to do something with it. One of the programs included in XB256 is a sound list compiler. This takes CALL SOUNDs and turns them into an assembly language sound list compatible with the sound list player in XB256 and also Matt Haggarty's sound list player. This works fine but one of its drawbacks is that the arguments can only be numbers. There is a large amount of BASIC/XB music existing for the TI that use mathematical expressions in the CALL SOUND statements. My idea was to write an XB subroutine called SLIST (or something similar) that starts at line 30000 and merge it into an XB music program. Then use Classic 99's clipboard to transfer the XB program to a text editor. Replace every CALL SOUND with CALL SLIST, then rewrite the program with "Paste XB". Now when the XB program runs it will go to SLIST instead of doing a CALL SOUND. SLIST was to take the variables passed, put together a sound list for that particular CALL SOUND and save it to disk. Unfortunately, while CALL SOUND can cope with 3 to 9 variables, we learned above that a user written subroutine expects a fixed number of variables to be passed. I can't see any way to to get around this that isn't very cumbersome. However, it could be done with an assembly language subroutine. An A/L sub can look to see how many variables were passed and with that information know how to put together the numbers to make up the sound list. Let's say the A/L sub is called "SOUND". Use a text editor to change CALL SOUND( into CALL LINK("SOUND", Then when the program runs, it goes to the assembly language SOUND, passing the same values that would have gone to the XB CALL SOUND. The A/L SOUND creates a sound list for each CALL SOUND as it is played and writes it to disk. See next post for proper response. Not very savvy with the AA Editor tonight... Edited August 2, 2014 by InsaneMultitasker Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted August 2, 2014 Share Posted August 2, 2014 I can think of two possibilities: 1. Can I intercept the CALL SOUND routine and capture the data that is being sent? 2. CALL SOUND requires a duration and then both a frequency and volume, per channel. Which means CALL SOUND must contain 3,5,7, or 9 variables. I would think you could write a search/replace routine to check for the number of commas in the CALL SOUND routine and then replace "SOUND" with one of four user-defined subprograms representing the variable count. You would use the four subprograms to write to a single file thus maintaining the proper sound list order. I replaced the last character of SOUND with the total variables. Depending on token and other conventions, this may not be the best choice for replacement. Fortunately, file IO is not constrained by subprogram boundaries. 1 OPEN #1:"DSK1.SOUNDLIST",OUTPUT 2 !program here 11999 CLOSE #1::END 13000 SUB SOUN3(A,B,C)::PRINT #1:A,B,C::SUBEND 15000 SUB SOUN5(A,B,C,D,E)::PRINT #1:A,B,C,D,E::SUBEND 17000 SUB SOUN7(A,B,C,D,E,F,G)::PRINT #1:A,B,C,D,E,F,G::SUBEND 19000 SUB SOUN9(A,B,C,D,E,F,G,H,I)::PRINT #1:A,B,C,D,E,F,G,H,I::SUBEND If you required integers on output (presuming some math generates non-integers), you could generate them with INT during the file IO. For example: 13000 SUB SOUN3(A,B,C)::PRINT #1:INT(A),INT(B),INT©::SUBEND I would guess the search/replace would need to be done on a text file, unless you have a way to check the token and replace it with the user defined subprogram. Seems Classic99 would do nicely for re-importing a text file into XB. Doesn't RXB have some similar support? Edit: posted before I was done writing Quote Link to comment Share on other sites More sharing options...
RXB Posted August 2, 2014 Share Posted August 2, 2014 (edited) Edit: posted before I was done writing Yea you write a CALL USER text file that can use the same commands as LIST a program, loads a new program and takes apart the text to make another program in any format you want. Take a look at USER in RXB and if you can type it then CALL USER can do it. Edited August 2, 2014 by RXB Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted August 2, 2014 Share Posted August 2, 2014 (edited) Oops. Didn't see your post (#19) there, senior_falcon. Sorry. Edited August 2, 2014 by sometimes99er Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted August 2, 2014 Author Share Posted August 2, 2014 In post #20, RXB replied "This is already built into RXB:" Your example does not show a sound list being created from CALL SOUNDs in a music program. It takes an already created sound list and loads it into VDP. In post #22, InsaneMultitasker said:2. CALL SOUND requires a duration and then both a frequency and volume, per channel. Which means CALL SOUND must contain 3,5,7, or 9 variables. I would think you could write a search/replace routine to check for the number of commas in the CALL SOUND routine and then replace "SOUND" with one of four user-defined subprograms representing the variable count. You would use the four subprograms to write to a single file thus maintaining the proper sound list order. I replaced the last character of SOUND with the total variables. Depending on token and other conventions, this may not be the best choice for replacement. I had thought about that and rejected it, my thinking being that an array might be used such as NOTE(X,Y,Z) and the extra commas would cause problems. Or, since computer programmers are a devious bunch, something like VAL(SEG$,A$,I,3) could turn up. But realistically those possibilities seem very remote. To me the best bet would be to use an assembly subprogram to search the XB program in high memory for CALL SOUND. If found then count up the commas and plug in the appropriate number. I will take a look at some of the music programs that I have and see if Insane's approach might be a viable one. 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.