Jump to content
IGNORED

Optional variables in user written subprogram?


Recommended Posts

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.

Link to comment
Share on other sites

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
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 by RXB
Link to comment
Share on other sites

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 !? :|

 

optional.png

 

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.

Link to comment
Share on other sites

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)

 

:D

 

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 by sometimes99er
Link to comment
Share on other sites

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!

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

 

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

 

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 by RXB
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 by RXB
Link to comment
Share on other sites

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 by InsaneMultitasker
Link to comment
Share on other sites

 

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 :dunce:

Link to comment
Share on other sites

Edit: posted before I was done writing :dunce:

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 by RXB
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...