Jump to content
IGNORED

Self deleting code in Turbo Basic XL


Recommended Posts

What's the best way to "self delete" code after it has been used and won't be needed again ( to free memory during execution)?

 

I have a program that has a LOT of lines of DATA to load. However, once it is loaded it is never referenced again.

 

So, in Turbo Basic XL I just added a DEL 20000,32000 to the code in-line after the DATA reads are completed.

 

Works like a charm in Turbo Basic XL.

 

However, I want this program to be Compiled for speed with Turbo Basic XL Compiler.

 

The Compiler chokes on the DEL 20000,32000 statement. So, I am forced to remove that before I can compile.

 

Does anybody have suggestions on ways to accomplish this in the Compiled version as well?

 

Thanks!

-Eric

Link to comment
Share on other sites

I believe that the compiler will not be able to work with self deleting code like you use because your "del" command is referencing lines of code, which do not exist when it is compiled. On compilation, they will be individual values in memory locations.

 

I would copy the data from somewhere into your buffer. That somewhere that it comes from will probably be better off compressed somewhere, perhaps on disk and then loaded into your buffer as it is required. You may not want to compress it, that is up to you. You'll need to allocate some known free memory for your buffer.

  • Like 1
Link to comment
Share on other sites

I imagine a compiled program has no provision for insertion, moving or deletion of parts of the program.

 

The best bet is probably to have data resources in external files, read them into arrays, strings, memory, <whatever> in the most efficient format possible, e.g. 2 byte integers rather than floating point to save memory.

 

Alternate might be to have variables declared to static strings within the program. Whether it works, unsure, and it'd be more suited to string data than numeric.

 

e.g.

1000 A(1) = ADR ("Text line 1")

1010 A(2) = ADR("Text line 2")

 

In that form, the strings only exist once and can be referred by memory addresses that are put into the array. You can even change bytes within the string but of course need to take care with not going out of bounds and trashing something else.

Link to comment
Share on other sites

I imagine a compiled program has no provision for insertion, moving or deletion of parts of the program.

 

The best bet is probably to have data resources in external files, read them into arrays, strings, memory, <whatever> in the most efficient format possible, e.g. 2 byte integers rather than floating point to save memory.

 

Alternate might be to have variables declared to static strings within the program. Whether it works, unsure, and it'd be more suited to string data than numeric.

 

e.g.

1000 A(1) = ADR ("Text line 1")

1010 A(2) = ADR("Text line 2")

 

In that form, the strings only exist once and can be referred by memory addresses that are put into the array. You can even change bytes within the string but of course need to take care with not going out of bounds and trashing something else.

Rybags, this is really interesting. I have never used the ADR function on a string that way.

 

How would this be used to access the data by memory address after it is stored then? Can you show another simple example?

 

Thanks so much.

-Eric

Link to comment
Share on other sites

ADR is often just used as calling address for a USR function. In the mentioned way though, the assembly routines are limited in size to ~ 100 bytes as well as having to be location independant.

Whether it would work with a compiled program - unknown. Compiling will usually generate code that's to execute in a fixed location so no reason it shouldn't.

Other often use for ADR is parameter for USR, in this embedded string situation you might want to alter what's in the string or just use the whole string as a temporary work area.

Link to comment
Share on other sites

Not really a Turbo BASIC programmer. Assuming it works similar to Atari BASiC I would say convert all data statements to strings and use Rybag's technique for text because of the way Atari BASIC works: All numbers are stored as floats with a few other tips.

? FRE(0)

32130

 

Ready

10 DATA 65,66,67,68,69,70,71,72,73

20 ? FRE(0)

RUN

32083

 

Ready

10 A=ADR("ABCDEFGHI")

20 ? FRE(0)

RUN

32093

 

Not sure where the break even point occurs, maybe ~5 data statements. IOW: No benefit if you have less then 4-5ish data statements.

 

I haven't checked it out, but you would probably be better off using string assignments over arrays for the same floating point reasons.

A(1)=ADR("ABCDEFGHI")

Stores the address of the string as a 6 byte floating point number where

A1$="ABCDEFGHI"

Stores it as a 2 byte variable.

 

I think I have seen people use the same string variable for huge strings. May have even been me! You can use 64k strings<or is it 32k?> in Atari BASIC so you can just keep building the string with a simple string assignment i.e.

10 DIM A1$(11)

20 A1$(1)="HELLO"

30 A1$(6)=" WORLD"

40 ? A1$

 

RUN

HELLO WORLD

 

There were a number of programs to squeeze every oz out of Atari BASIC. I think Mr. White with Atari wrote several that would reduce the length of variable names to two characters and maximize line length. Ditto for utilities that would take DATA statements and put them into strings.

Link to comment
Share on other sites

I think Mr. White with Atari wrote several that would reduce the length of variable names to two characters and maximize line length. Ditto for utilities that would take DATA statements and put them into strings.

 

I'm somewhat rusty with my Turbo Basic, but wasn't it that you could assign a value for a number to save bytes...?

i.e. 10 N6=6

And then every time you want to use the value '6' in your program, used use N6 as your reference to save 4 bytes from the 6 normally used to reference 6

 

As for long strings, there are all the big long strings used in type in listings which were inside BASIC but were machine language programs. That might be useful in this case...

 

Perhaps (if the compiler is ok with it), you could use :

RESTORE 1000+(10*LEVELNUMBER)

to point to the data that you want....

Is that possible when line numbers are stripped out?? Perhaps not...

Link to comment
Share on other sites

... I have a program that has a LOT of lines of DATA to load. However, once it is loaded it is never referenced again. ...

Do you use a DOS? If your DATA lines contain values between 0 and 255, then maybe it suffices when you safe them to 8bits binary data files first. Why deleting before overwriting data area during the next file read? After compile/runtime I think it's easy to load and access the data files:

 

DATA0001.BIN
DATA0002.BIN
DATA0003.BIN
...
Edited by analmux
Link to comment
Share on other sites

Rybags, this is really interesting. I have never used the ADR function on a string that way.

 

How would this be used to access the data by memory address after it is stored then? Can you show another simple example?

 

Thanks so much.

-Eric

The ADR function gives you back the address of the string as its stored in your program. You can use this address with PEEK to get back the first byte of the string. You can add 1 to the address and PEEK that to get the second byte of the string, etc.

 

10 X=ADR("0123456789")
20 FOR I=0 TO 9
30 PRINT PEEK(X+I)
40 NEXT I

That will print the ATASCII codes for the numbers 0-9, i.e. 48-57 decimal.

 

You can use the string data in-place as you would with data that you POKEd, or you could move it somewhere else if alignment is important. For example, you could encode a position independent assembly language routines in ATASCII:

 

10 X=ADR("XXXXXXXXX")
20 D=USR(X)

You could encode your display list in ATASCII but display lists can't cross a 1K boundary and you can't be sure where the string will end up in memory so you can use MOVE to copy the data from the location of the string in your program to some location in high memory with the correct alignment:

 

10 MOVE ADR("XXXXXXXXX"),$A000,20
20 DPOKE $230,$A000

Here "20" would be the length of the display list in bytes.

 

I used the above technique in my Cavern 10 entry into the Basic Ten-Liners contest earlier this year. I used ADR("") to store the display list, the font, the screen data, etc. in lz4 compressed form. I used MOVE to copy the data into continuous high memory and then decompressed it into higher memory with the correct alignment. It sounds like this probably wouldn't help you though if you have a lot of code since there's probably not enough memory to have a copy of the data as strings in your code and another copy in high memory. In this case, probably better to load the data from disk directly into high memory as others have suggested. Though perhaps there is an easy way to link the executable generated by Turbo Basic Compiler with an object file containing the data. If that were the case, then whenever you ran the new executable it would automatically load the data into place exactly where you want it without requiring any disk I/O within your program itself.

  • Like 1
Link to comment
Share on other sites

DATA statements just store in raw Ascii. The problem with data is you waste memory if storing lots of small items since each comma uses a byte but isn't contributing to useful data.

Also you're replicating information, unless in an uncompiled situation you read the items then delete the data lines.

Link to comment
Share on other sites

I'm somewhat rusty with my Turbo Basic, but wasn't it that you could assign a value for a number to save bytes...?

i.e. 10 N6=6

And then every time you want to use the value '6' in your program, used use N6 as your reference to save 4 bytes from the 6 normally used to reference 6

 

As for long strings, there are all the big long strings used in type in listings which were inside BASIC but were machine language programs. That might be useful in this case...

<snip>

Ohhhh that brings back painful memories! :)

 

I think several telecommunication programs like AMIS and AMODEM 4.2 did exactly that to save a few bytes for a bigger buffer. Some of the other programs being discussed now like Temple of Asphai did the same thing. Made it even more difficult to sort through the spaghetti code.

 

I think the longest string I ever encoded was something like three Microillustrator screens for an animation. Had to have been one of the worlds worst ideas. 23k of string with 8k of memory used for display. I think it only left a few bytes for the program. I keep telling myself "it's a hobby."

 

I really should start programming in BASIC again. After a few decades of structured programs I think I could actually write programs that could be followed by a skilled programmer.

Link to comment
Share on other sites

 

The ADR function gives you back the address of the string as its stored in your program. You can use this address with PEEK to get back the first byte of the string. You can add 1 to the address and PEEK that to get the second byte of the string, etc.

 

10 X=ADR("0123456789")
20 FOR I=0 TO 9
30 PRINT PEEK(X+I)
40 NEXT I
That will print the ATASCII codes for the numbers 0-9, i.e. 48-57 decimal.

 

You can use the string data in-place as you would with data that you POKEd, or you could move it somewhere else if alignment is important. For example, you could encode a position independent assembly language routines in ATASCII:

 

10 X=ADR("XXXXXXXXX")
20 D=USR(X)

You could encode your display list in ATASCII but display lists can't cross a 1K boundary and you can't be sure where the string will end up in memory so you can use MOVE to copy the data from the location of the string in your program to some location in high memory with the correct alignment:

 

10 MOVE ADR("XXXXXXXXX"),$A000,20
20 DPOKE $230,$A000

Here "20" would be the length of the display list in bytes.

 

I used the above technique in my Cavern 10 entry into the Basic Ten-Liners contest earlier this year. I used ADR("") to store the display list, the font, the screen data, etc. in lz4 compressed form. I used MOVE to copy the data into continuous high memory and then decompressed it into higher memory with the correct alignment. It sounds like this probably wouldn't help you though if you have a lot of code since there's probably not enough memory to have a copy of the data as strings in your code and another copy in high memory. In this case, probably better to load the data from disk directly into high memory as others have suggested. Though perhaps there is an easy way to link the executable generated by Turbo Basic Compiler with an object file containing the data. If that were the case, then whenever you ran the new executable it would automatically load the data into place exactly where you want it without requiring any disk I/O within your program itself.

 

These are all really great suggestions and give me lot to work with.

 

I am thinking it i put all of my data into a long hard-coded string, then move that into higher memory at execution, then I could just reset the long strong to null and avoid the duplicate memory issue.

 

Regardless, many new approaches for me to experiment with, which was exactly what I was looking for!

 

Thanks!!!

Link to comment
Share on other sites

I used to do that a lot.

 

You can save memory in the first place by putting the constants into Data statements. And since numeric vars are zero at first usage you don't need to worry about N0.

 

1000 READ N1,N2,N3,N5,N10 : DATA 1,2,3,5,10

i didn't realize that would be more efficient, this should help me quite a bit from a memory standpoint. Nice.

Link to comment
Share on other sites

There is this trick, which I used a variant of when coding my TurboBASIC game Sky Scraper.

 

Let's say you wanted to delete lines 1000-2000 from your code after you executed them. try this:

 

1000 REM This Line Will Be Deleted

2000 REM So Will this

3000 POSITION 0,2:? "DEL 1000,2000:POKE 842,12:CONT

3010 POSITION 0,0:POKE 842,13:STOP

3020 REM rest of program here

 

POKE 842,13 forces the computer into forced-read mode, it automatically presses RETURN continuously. Any statements it encounters on screen will be treated as being in immediate mode. So, you place the statements on screen with PRINT statements, making sure to put in a POKE 842,12:CONT in there so that the program resumes afterwards. Then position your cursor at 0,0 and execute a STOP command.

 

My use for this method in Sky Scraper, was to "ENTER" new game levels from disk everytime you finish a level. ENTER will not work during program execution because it stops the program, so you have to use the forced read method in this case.

 

Needless to say, this method will not work with compiled programs, of course.

Edited by Synthpopalooza
Link to comment
Share on other sites

I really should start programming in BASIC again. After a few decades of structured programs I think I could actually write programs that could be followed by a skilled programmer.

I've thougt about this myself, but come to a different conclusion. I've been doing structured programming on very large systems for so long, I don't think I could go back :(

Link to comment
Share on other sites

I've thougt about this myself, but come to a different conclusion. I've been doing structured programming on very large systems for so long, I don't think I could go back :(

 

I've been doing the same as you for the last few years and then I went back the other week to take a look at some of my old Turbo Basic code.

 

Admittedly it was a bit of a shock but I understood it (once read through) and could add to it. You have to do it with one eye shut though! :)

 

Go on, grin and bear it!

Link to comment
Share on other sites

 

I've been doing the same as you for the last few years and then I went back the other week to take a look at some of my old Turbo Basic code.

 

Admittedly it was a bit of a shock but I understood it (once read through) and could add to it. You have to do it with one eye shut though! :)

 

Go on, grin and bear it!

I am - but I am now bearing it doing pure 6502 code :)

Link to comment
Share on other sites

  • 4 weeks later...

That actually is the best way of combining pure data with a program (be it written in ASM or TB and then compiled). The data segment has to be added before the XEX part and you're done. Of course you have to make sure that the memory location is safe. TB Compiler copies stuff around quite a bit in the memory when the executable starts.

Link to comment
Share on other sites

  • 8 months later...

How about compiling and linking it to an executable file, then appending a segment that loads the data at a specific address? I'm not in front of an Atari now, but I don't see why it wouldn't work.

Coming back to this suggestion... how do I go about doing this for a compiled TBXL program?

 

Right now I have a program that uses a BGET to load data from a separate XEX file.

 

When I compile it everything works fine as long as I have the separate XEX file available in the right location.

 

I'd prefer to ultimately have everything in one single executable file. I know I can use TBLINKER to pull the runtime and the .CTB file together into one executable, but at this point I still have to have a separate XEX file with my data.

 

Is there a way to do ALL of this within a single file, including what i currently have in the separate XEX/data file?

Link to comment
Share on other sites

A simple way might be to just link the data as segment at the begin of AUTORUN.SYS (runtime).

I check the segments and the area $8000.... appears to be unused.

A short test also worked.

 

AUTORUN.SYS:
<your segment starting at $8000>
<original content of autorun.sys)

 

 

post-17404-0-03459600-1443255556_thumb.png

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...