Jump to content
erichenneke

LOAD"D:" and RUN vs. RUN "D:"

Recommended Posts

I've noticed that when a BASIC program is LOAD'ed and then RUN, memory is populated differently than if it same program is just RUN directly with a RUN "D:" command. For example, the DL will be located in a different memory position, and the variable table is located differently, etc.

 

For example:

LOAD "D:PROGRAM.BAS"

RUN

 

is different than

RUN "D:PROGRAM.BAS"

 

when I look at the resulting populated memory locations.

 

Any idea why that is the case?

 

-Eric

 

  • Like 1

Share this post


Link to post
Share on other sites

The commands you type in immediate mode are inserted into the program as an invisible line 32768 before being executed. This shifts all tables after the statement table (arrays, strings, runtime stack). In the first case, BASIC loads the program and then replaces line 32768 with RUN. In the second case, line 32768 gets changed before the load and run occurs, so the program starts with whatever line 32768 it was saved with, usually a SAVE command.

 

The variable table itself shouldn't be at a different location since it's before the statement table and thus only moves according to MEMLO. Strings and arrays in the variable table will get their memory after the statement table, though, so they will shift.

  • Like 2

Share this post


Link to post
Share on other sites

The commands you type in immediate mode are inserted into the program as an invisible line 32768 before being executed. This shifts all tables after the statement table (arrays, strings, runtime stack). In the first case, BASIC loads the program and then replaces line 32768 with RUN. In the second case, line 32768 gets changed before the load and run occurs, so the program starts with whatever line 32768 it was saved with, usually a SAVE command.

 

The variable table itself shouldn't be at a different location since it's before the statement table and thus only moves according to MEMLO. Strings and arrays in the variable table will get their memory after the statement table, though, so they will shift.

Yes! Exactly what I am seeing . All the strings and arrays in the table shifted.

 

So, is there any way to trick this? For example, is there a way to save the program in such a way that this line 32768 is a RUN ?

 

I am trying to make sure the program will behave exactly the same if executed with a RUN "D:" the same as it would with a LOAD"D:" and then RUN. I want the resulting populated memory to all be identical in both scenarios.

 

Is it possible?

 

Thanks!

-Eric

Share this post


Link to post
Share on other sites

Sort of:

LOAD "D:FOO.BAS"
0 TRAP 32766:STOP
RUN
0
32765 END
32766 SAVE "D:BAR.BAS"
-1

...but you have another problem. Your program addresses will also track MEMLO and will shift depending on DOS. You could solve that by fixing a specific DOS boot sequence... but if you were doing that you wouldn't have a need for this. Therefore, it's better to try to get rid of your dependency on a fixed address. One way to do this is to have the first array in your program be a variable-sized string that eats all memory to a defined address. This then aligns all arrays and strings allocated afterward.

 

 

Share this post


Link to post
Share on other sites

The dummy line that performed the SAVE is never executed on a subsequent reload.

AFAIK there's no way to get a Basic program to just autorun if it came in via a LOAD or CLOAD command.

 

Possibly you could do a hack that changes the offsets of the variable table and program such that they got loaded into system areas that caused a command to be buffered.

But the problem with that is that with Basic and most languages you have no guarantee of having a known start of memory (MEMLO) location because the DOS used and how it's configured will change that.

 

With the ENTER command it's easy to do autorun because all that command is doing is telling Basic to open a file and treat the incoming data as if it was typed via E:

 

So, to that end all you'd need to do is add an extra line at the end of the file with a RUN or GOTO statement.

 

 

Once again, counting on a known scenario of populated memory isn't a good thing. You're better off doing adjustments within the program which can be done fairly easily. Common things are using ADR(STRINGVAR$) to get string addresses or hopping through the variable value table to force the address of strings.

 

So, a cheap and nasty way to force an autorun of a Basic program could be having it as a 2 part load process.

 

e.g.

ENTER "D:GAME1.LST"

 

command ENTERS a stub program which can in fact just be a bunch of immediate mode commands sort of like a PC batch file (though some commands like END, RUN, NEW will terminate the file).

 

GAME1.LST contains the following:

GR. 0
?  ? "GR. 0:RUN ";CHR$(34);"D:GAME1.BAS"
POS. 0,0 : POKE 842,13

GAME1.BAS is your target program.

To hide what's going on, add SE. 1,9,4

after the first GR. 0 statement.

Edited by Rybags

Share this post


Link to post
Share on other sites

Sort of:

LOAD "D:FOO.BAS"
0 TRAP 32766:STOP
RUN
0
32765 END
32766 SAVE "D:BAR.BAS"
-1

...but you have another problem. Your program addresses will also track MEMLO and will shift depending on DOS. You could solve that by fixing a specific DOS boot sequence... but if you were doing that you wouldn't have a need for this. Therefore, it's better to try to get rid of your dependency on a fixed address. One way to do this is to have the first array in your program be a variable-sized string that eats all memory to a defined address. This then aligns all arrays and strings allocated afterward.

 

 

Yeah, i wouldn't be doing it this way but it's for a 10-liner and code space is at a premium of course, so I am hard-coding some string memory position dependencies. That's a great idea about starting with a variable-sized string. I'll give that a go.

 

Thanks again.

-Eric

Share this post


Link to post
Share on other sites

I didn't realize you could embed immediate mode commands in a LST file and that they would actual execute when ENTER'd, but it totally makes sense.

 

I just tried putting RUN as the last line in my LST file, and ENTER'd it and of it auto-ran great, and my hard-coded memory location dependencies all lined up fine.

 

Still not exactly what I am after because I really want it to be a SAVE'd basic program not a LIST'd file, but this is a good back up plan.

 

Now I'll go work on removing the dependencies which, I totally agree, would be the better approach if I can make it fit into the 10 lines. :)

 

-Eric

Share this post


Link to post
Share on other sites

For PMGs contained in strings the cheap/nasty trick is to DIM the string so large that it will always contain the 1K or 2K area needed for the PMGs regardless of where MEMLO is, but so long as free Ram isn't short.

 

like:

10 DIM PM$(4095) : P=ADR(PM$) : PM=INT(P/2048) * 2048: IF PM<P THEN P=P+2048

That grabs a chunk of memory and sets PM to the 2K base where 1-line PM graphics would start (note of course first 3 256 byte blocks unused then 256 for missiles and 4x256 for players).

 

But since you're using strings you'd probably also want to calculate the index in the string where each object is stored.

Edited by Rybags

Share this post


Link to post
Share on other sites

I didn't realize you could embed immediate mode commands in a LST file and that they would actual execute when ENTER'd, but it totally makes sense.

 

I just tried putting RUN as the last line in my LST file, and ENTER'd it and of it auto-ran great, and my hard-coded memory location dependencies all lined up fine.

 

Still not exactly what I am after because I really want it to be a SAVE'd basic program not a LIST'd file, but this is a good back up plan.

 

Now I'll go work on removing the dependencies which, I totally agree, would be the better approach if I can make it fit into the 10 lines. :)

 

-Eric

 

I guess that it is not allowed to change the Atari BASIC environment to a given starting point before loading the game. Those extra instructions/statements in the LST file might count as lines (without a number).

I was trying to change the MEMLO and related pointers at runtime to make strings fit some fixed memory locations and use string slice operations to copy chuncks of memory in Atari BASIC as fast as a MOVE statement does in TurboBASIC XL. It didn't work as well as I thought,

 

The main problem is that initialization now takes too much space for a "stock" PUR-80 tenliner game.

  • Like 1

Share this post


Link to post
Share on other sites

an immediate mode run should not count as a line but then people might try to use that and bend it for all sorts of stuff.. since it is not specified that must a program self run... it could just be entered they can type run.... who cares if they have to just so long as it works.

Edited by _The Doctor__
  • Like 1

Share this post


Link to post
Share on other sites

Hi!

 

The main problem is that initialization now takes too much space for a "stock" PUR-80 tenliner game.

Yes, one posible shortcut is assuming no DOS, so the program starts on $700 always, and saving with CSAVE produces the same immediate line length as "RUN", so the problem of running with "RUN *" or "CLOAD / RUN" is avoided.

 

Look at this program, that produces a "starfield" effect:

 

post-18634-0-29768900-1518278717_thumb.png

 

Attached is a (zipped, because we can't post .cas) CAS file, load with "CLOAD" and run, also there is a BAS file that won't work with DOS, but can be loaded with an emulator "H" device.

prog.zip

prog.bas

Share this post


Link to post
Share on other sites

 

I guess that it is not allowed to change the Atari BASIC environment to a given starting point before loading the game. Those extra instructions/statements in the LST file might count as lines (without a number).

I was trying to change the MEMLO and related pointers at runtime to make strings fit some fixed memory locations and use string slice operations to copy chuncks of memory in Atari BASIC as fast as a MOVE statement does in TurboBASIC XL. It didn't work as well as I thought,

 

The main problem is that initialization now takes too much space for a "stock" PUR-80 tenliner game.

Sounds like you and I are both chewing on the exact same challenge at the moment. :)

Share this post


Link to post
Share on other sites

You might be able to set the string/array pointer to some address before any arrays are defined. But the stuff after it like runtime stack would also need to be moved.

Whether this would work, unknown. But for practically any Dos there should be free Ram starting at $4000

 

A fast trick for relocating strings can be to make sure the strings are the first variables defined. Then you could get away without needing code to hop through the variable pointers.

Edited by Rybags
  • Like 1

Share this post


Link to post
Share on other sites

Sounds like you and I are both chewing on the exact same challenge at the moment. :)

 

Yup! ;)

 

As it was too much work to change the string pointers (and too much space for the smaller category), I tried my other idea: to initialize a big string, to find the first char position that it is at a 1K, 2K or the required boundary and to point screen area to that byte by modifying the pointer in the DL. Also a PMBASE could be set using the same procedure (or both at once). Then, all screen and P/M data may be moved arround using (sub)string assignments.

 

I did a proof of concept that, after some hours, turns into a complete game... It is another one like Descend, Streamliner or Carrera, but at Atari BASIC speed, i.e. slower! Now I must prepare the required docs to submit it. :-D

  • Like 1

Share this post


Link to post
Share on other sites

 

Yup! ;)

 

As it was too much work to change the string pointers (and too much space for the smaller category), I tried my other idea: to initialize a big string, to find the first char position that it is at a 1K, 2K or the required boundary and to point screen area to that byte by modifying the pointer in the DL. Also a PMBASE could be set using the same procedure (or both at once). Then, all screen and P/M data may be moved arround using (sub)string assignments.

 

I did a proof of concept that, after some hours, turns into a complete game... It is another one like Descend, Streamliner or Carrera, but at Atari BASIC speed, i.e. slower! Now I must prepare the required docs to submit it. :-D

Yeah, that's the approach i am using too. Using a dummy string upfront with a variable DIM size to make sure the first "real" string starts exactly where I want it to be. Then everything else falls into place.

 

Jumping through the variable table works well, but takes up way too much precious real estate in the 10-liner code.

Share this post


Link to post
Share on other sites

The variable string method needs more bytes in the declaration than the variable index in a big string. The counterpart of the variable index is that more bytes are needed in the code, and the total number has to be to the number of times that the variable is added to the string slice.

 

The first version of my experimental game, "deep forest", used the calculated index, but the second one, "deep canyon", used the variable string declaration because that saved many bytes in the game loop. That also allowed me to add more features and difficulty because I could also fit the start of the loop with a beginning of a line, and then remove an endless FOR loop, saving more bytes for the initialization.

 

What I couldn't add was data for a new charset, so I had to keep the default font in ANTIC mode 4, just like your nice game.

Share this post


Link to post
Share on other sites

Yep, looks like we've both been working through the same challenges with Atari BASIC. After going with the variable string-length method to ensure my strings are starting at an exact/predictable memory location, I was able to fit more features in like scoring and keeping track of best score, and also made the computer logic more challenging to play against.

 

Using the method to skip through calculated steps of the variable table didn't leave me with enough room to do any of that before.

 

-Eric

Share this post


Link to post
Share on other sites

Another method to get a string on a known boundary - do a bit of calculation beforehand then allocate a dummy string of size X that takes up the slack space meaning your string will then fall on the boundary you want.

  • Like 1

Share this post


Link to post
Share on other sites

Another method to get a string on a known boundary - do a bit of calculation beforehand then allocate a dummy string of size X that takes up the slack space meaning your string will then fall on the boundary you want.

Yes , that's exactly what I am doing. Works great!!!

Share this post


Link to post
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...