Jump to content
  • 0
Starsickle

Breaking up Execution with Multiple Files

Question

So, this is something I will need out of necessity (1120 lines and currently at 44kb) and not entirely sure how to do by just looking at the C64 wiki. It describes how LOAD may be used, but only at the start of a program with little description of how this saves Program Memory or can benefit Program Flow.

Let us say we have a fairly large program and want to break up its raw number of lines to keep memory free. What essential components do I need to tell a program to LOAD THIS, DO THIS, and then GO BACK WHERE YOU WERE?

Basically - I'm aiming for the framework to execute a GOSUB but with a file. That way, within the program framework, I can offload...

PROGRAM START
SYSTEM SETUP
DATA ALLOCATION
DATA INITIALIZATION (THIS)
MAIN LOOP START
DRAW (THIS TOO, BUT SPECIFIC)
INPUT
PROCESS (AND THIS  - BUT SPECIFIC PROCESSES/OPERATIONS)
CONTINUE
MAIN LOOP END
PROGRAM TERMINATION

Perhaps I just need an illustrative example. It's not apparent LOAD can be used this way, as it "returns to the very beginning" of the originating file. https://www.c64-wiki.com/wiki/LOAD

Thanks in advance.

Share this post


Link to post
Share on other sites

9 answers to this question

Recommended Posts

  • 0

You're seeking to do overlays from a basic program? woah, not sure if that's possible at all.... 

It can be done by loading assembly code programs at certain locations in memory, SYS into them, and just continue trucking in your basic program...   But loading alternate pieces of basic code at different locations in memory? I have no idea how to pull that off 🙂 

Share this post


Link to post
Share on other sites
  • 0

This has been done on the C64; I vaguely recall a Compute! article that a dude pointed out to me in the C64 Software Development forum on Facebook.

So, it is possible to do on the X16.

 

Share this post


Link to post
Share on other sites
  • 0

The Commodore and Commander BASIC interpreters support "program chaining", but they have an annoying flaw.

After a BASIC program "executes" a LOAD statement, the interpreter goes to the first line in the current (maybe newly loaded) program.  The existing variables aren't erased -- the new program can use all of the variables from the old program!

The flaw is that those variables aren't moved out of the way.  If the new program is bigger than the old one, then it corrupts the variables!  And, if it stores anything, then it "stomps" on its tail!  Therefore, the first program in a chain must be the biggest of them.  (Therefore, the variables will be at high enough addresses to be safe from all of the other programs in the chain.)

The annoying part is that most start-up programs want to be small introductions to the group of programs.  Some programmers resort to making the first file artificially huge.

The chain communicates through the shared variables.  Often, the first line in each program is either an if statement or an on ... goto statement.  A "previous" program will set a certain variable to some non-zero value before loading the next file.  The first line in the next file will go to some other part of the program based on that value.  (If that variable is zero, then the program knows that it is the first one in the chain.)

  • Like 1

Share this post


Link to post
Share on other sites
  • 0

cc65's CBM/X16 libraries have an exec() function that exploits BASIC's chaining feature.  But, it communicates through "command line arguments", similarly to standard functions such as execvp().

Share this post


Link to post
Share on other sites
  • 0

So, let's say I were making an engine. I could basically allocate the variables that I'll always be using in my programs anyways then LOAD the actual program? That could be worth the code savings.

START.PRG
INIT.PRG
GAME.PRG

It's possible I might just have arrived too early and these features may come to be, but considering we have the potential for unlimited program space on media - this would be a very powerful capability if were to be figured out.
 

Share this post


Link to post
Share on other sites
  • 0
3 hours ago, Greg King said:

After a BASIC program "executes" a LOAD statement, the interpreter goes to the first line in the current (maybe newly loaded) program.  The existing variables aren't erased -- the new program can use all of the variables from the old program!

This is potentially helpful - I could very well just fracture off engine initialization (Screen sizes, etc.). Then DATA INIT runs and all the program's data can be allocated, read, and initialized. That sends it back to the main, where a control variable (as in the wiki example) now sends control to the main game. The main game reads the control variable as a stateID. The potential problem here is going back to the first might accidentally reset some variables because they are initialized in good practice at the start.

I will try tinkering with this.

EDIT: This is the example I'm working on.

STARTDEMO.PRG

16 REM // LS% //LOADED FILE STATE - CONTROLLING THE LOADED FILE.
15 IF LS%=0 THEN : GOSUB 100 : REM //DATA NOT LOADED.
16 IF LS%=1 THEN : GOSUB 200 : REM //DATA LOADED, PROGRAM NOT.
17 IF LS%=2 THEN : GOSUB 1000 : REM //PROGRAM LOADED. GO MAIN LOOP.
18 GOTO 4000
100 REM //ROUTINE - LOAD ANOTHER FILE AND INIT DATA.
101 LOAD "INITDEMO.PRG", 8,1
200 REM //ENGINE SETUP AND INITIALIZATION=====================================
201 VN$="0.0.1" : VD$="SEPTEMBER 15TH, 2020"
202 FC%=5 : BC%=0 : FI%=0 : BI%=5 : COLOR FC%, BC%
203 SX%=640 : SY%=480
204 DIM GD%(3)
205 LS%=2
206 GOTO 1000
	
1000 REM //MAIN LOOP
1001 PRINT "DISPLAY SCREEN"
1002 PRINT "GET INPUT"
1003 PRINT "PROCESS INPUT"
1004 PRINT "LOOP"
1005 GOTO 1000
3000 END
4000 STOP


And one of its potential compantions - INITDEMO.PRG

16 REM // LS% //LOADED FILE STATE - CONTROLLING THE LOADED FILE.
20 DIM RGN$(3,3,3) : DIM SCTR$(3,3,3)
21 LS%=1
22 END



How's that?

Edited by Starsickle
Illustrative example.

Share this post


Link to post
Share on other sites
  • 0

But initdemo.prg doesn't load anything, so it would hit end and you are back at the command line. It doesn't load "into" the first program, it loads OVER the first one, and now it's first line is the program first line and its END is the end of execution.

One thing you can do, if initialization statements are eating up too much space is:

MAINGAME.PRG:

100 IF DB=1 THEN 200

110 DIM A$(40): DIM B$ (24) : REM etc.

120 DB=1: LOAD "ARRAYINIT.PRG", 8

200  REM rest of program here

ARRAYINIT.PRG:

10 REM initialization code

20 ..

200 LOAD"MAINGAME.PRG", 8

As long as INITARRAY.PRG is smaller than MAINGAME, the variables it's filling were created at the end of "maingame", in its first run, when it dimensioned them, then when it calls maingame back, the " dirty bit" DB let's it know it is on its second run, and can skip that part.

Share this post


Link to post
Share on other sites
  • 0

The biggest program doesn't need to create any variables.  Most of that can be done by some other (smaller) program.  The "size" is measured and set during the LOAD operation -- when that LOAD is done from the "READY." prompt.  Therefore, the first three code statements in your main (biggest?) program could be

30 ON RT% GOTO 50, 200, 800, (etc.)
40 LOAD "INIT VARS"
50 REM returned from "INIT VARS"
...


The "INIT VARS" program would create all of the variables (except RT%; it was created (and set to zero) when the first program first used it).  That initiation program would end by setting RT% to one; and loading the main program. (Note that your main program wouldn't set RT%.  The other ones would use it as a kind of "return code number".)

Of course, that "INIT VARS" program doesn't need to be the second one in the chain; it could be the third one.  Your second program could print a "splash screen" that announces your great game.  It would be run only once; therefore, it wouldn't care about RT%.  It would end by loading "INIT VARS" directly!

Share this post


Link to post
Share on other sites
  • 0

Yup. Greg nailed it.

The key is that when you use LOAD inside of a running program, variables do not get cleared. So you can use a variable to store "what do I do next?"
 

On 9/14/2020 at 3:39 PM, desertfish said:

You're seeking to do overlays from a basic program? woah, not sure if that's possible at all

It works fine with the LOAD command in the program. You just have to follow certain rules....


For example:
Program1
10 A$="HELLO"
20 LOAD "PROGRAM2",8
30 PRINT "PROGRAM1"

Program2
10 PRINT A$
20 PRINT "PROGRAM2"

If you save those as PROGRAM1 and PROGRAM2, then run PROGRAM1, it will set A$, then load and run PROGRAM2, printing 
HELLO
PROGRAM2
on the screen.

 

  • Thanks 1

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.

Guest
Answer this question...

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


×
×
  • Create New...

Important Information

Please review our Terms of Use