![]() |
Forum Index : Microcontroller and PC projects : CMM2 how to load and execute a second basic programm
Author | Message | ||||
digger72 Newbie ![]() Joined: 07/02/2021 Location: GermanyPosts: 4 |
Hello together. In MMBasic exists the EXECUTE command with which I can execute Basic commands. Unfortunately, this only works for single commands and not for complete Basic files from SD card. Is there a way to load and execute a second Basic program within my program and to return after its end? Many thanks in advance for any help. Best regards, Frank |
||||
Mixtel90![]() Guru ![]() Joined: 05/10/2019 Location: United KingdomPosts: 7865 |
Hi Frank, and welcome to the 'shed. :) I think EXECUTE "RUN myfilename$" does something like that on the CMM2. I've not tried it. I've not tried this on a PicoMite. You can use RUN "myfile$" from within a program, of course. All variables are destroyed and myfile$ can't be a variable, I don't think. On the PicoMite you can use FLASH CHAIN (which preserves variables), but you can't CHAIN anything else. . Edited 2025-01-09 23:06 by Mixtel90 Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
digger72 Newbie ![]() Joined: 07/02/2021 Location: GermanyPosts: 4 |
yeah i tried this, but "RUN" removes the active program and runs the new one. after this is finished there is no way to return to the previous state from before. The second Basic program should work like a dynamic loaded external function/extension at runtime. My use case is to start external tools from inside my application. |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10240 |
This isn't possible with MMBasic. Loading a program overwrites the variable space of the previous program |
||||
digger72 Newbie ![]() Joined: 07/02/2021 Location: GermanyPosts: 4 |
Yes, i understand, thats why RUN is not the right choice. The EXECUTE command does perfetly what i need, but only for one single command. I need the possibility to load some more Basic lines from an external file and execute them in the context of my running program. a loop with EXECUTE for all loaded Basic lines does not work for more complex code or functions/subroutines. Maybe there exist a trick to load an external Basic program and appending this to the running program? |
||||
Mixtel90![]() Guru ![]() Joined: 05/10/2019 Location: United KingdomPosts: 7865 |
No. To add to a program it would have to be in the editor. That's simply not possible as the editor has used up the variables area. I'm afraid that what you are asking for isn't possible. Once a program is running there is no way to change it without ending it as the editor doesn't exist. Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
PeteCotton![]() Guru ![]() Joined: 13/08/2020 Location: CanadaPosts: 543 |
Hear me out here - this might be a bit of a mad solution - and I haven't tried it - but here goes. STEP 1: You have your program called "MainProgram" and you have the second program called "SubProgram". Create an empty file called "SubProgram.inc" In MainProgram, at the start, put the following lines: GOTO StartOfSubProgram ReturnHere: ' Delete SubProgram.inc OPEN "SubProgram.inc" FOR OUTPUT AS #1 PRINT #1, "" CLOSE #1 Now at the very end of your program put the lines: StartOfSubProgram: #INCLUDE "SubProgram.inc" GOTO Returnhere: STEP 2: When you want to run SubProgram, copy the contents of "SubProgram.bas" to a new file called "SubProgram.inc", then run "MainProgram" again using the command: EXECUTE "RUN " + CHR$(34) + "MainProgram.bas" + CHR$(34) This will restart your program, but now the sub program is attached to the end. Your program will jump to the start of the subprogram and execute it. Of course, it will only return control to your MainProgram if it runs off the end of the sub program, but you could also search SubProgram.Inc for the END command (and not END IF/END SUB etc.) and change that to "GOTO ReturnHere". Even if this works (I'm not sure that it will), you will have to be careful that all of your variables and subs in the MainProgram are unique from the SubProgram - so I would prefix them all with an unusual set of characters e.g. "TD45_Variable". Also, you will lose any variables in memory on the restart - however you could save them to a disk file and reload them when the program restarts. This is all a bit hacky - but hey - at least I found a good use for the GOTO command! Edited 2025-01-10 01:39 by PeteCotton |
||||
JohnS Guru ![]() Joined: 18/11/2011 Location: United KingdomPosts: 4038 |
You would pretty much need an OS but there isn't one. (hmm, it would probably prevent what you ask for, anyway.) And on almost all of the supported devices there isn't enough memory either (the CMM2 is an exception). I suppose you could restructure MMBasic... Maybe move to Windows or Linux as then at least you have an OS and may have such as system(), though it may also not quite do what you want. BTW some of the ideas floated would only work if MMBasic doesn't tokenise things ahead of execution i.e. if it's a typical interpreter not a semi-compiler. John Edited 2025-01-10 01:49 by JohnS |
||||
Andy-g0poy Regular Member ![]() Joined: 07/03/2023 Location: United KingdomPosts: 75 |
I would think that you could do something to make this work, but it will need careful design. The "main" program would need to very carefully keep a record of all of it's variables. When you need to run the second program you write these variables to a file. Then you execute and run the second file when finished you then run the first program again and load the variables etc from the file. You would need to manage the first start carefully, but it would not be too hard. HOWEVER this is pretty much what FLASH CHAIN does. It runs another program leaving the variables intact. is this not good enough for your needs? Page 35 of the manual I have There is also the Flash Filesystem drive A: which might be useful Andy |
||||
Mixtel90![]() Guru ![]() Joined: 05/10/2019 Location: United KingdomPosts: 7865 |
Wrong machine, Andy. He's on about the CMM2, which doesn't have either flash slots or a A: drive in flash. Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
phil99![]() Guru ![]() Joined: 11/02/2018 Location: AustraliaPosts: 2610 |
Last year I did something similar (it was on a Pico but should work on a CMM2). When the main program started it looked for a Sub containing initializing values. If not found it Saved itself to a disk file then generated and appended lines to the end of the copy. These were two subroutines, the one held all the variable values the program would need when re-run and the other all the new data that it would need. (In your case that subroutine would contain the new commands.) It then RUN the disk file. See footnote in this post here. |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9593 |
I thought that the CMM series had the CHAIN command? Perhaps that was only on the CMM1 and earlier FW, and perhaps that command was removed from MMBASIC by the time the CMM2 came on the scene..... Smoke makes things work. When the smoke gets out, it stops! |
||||
phil99![]() Guru ![]() Joined: 11/02/2018 Location: AustraliaPosts: 2610 |
So using the method in my previous post the program would copy (SAVE fname$) itself to A: then append a Sub containing the #INCLUDE command. It would then RUN fname$ and at the appropriate point call the Sub. Precede the call with On Error Skip to prevent an error on the first run which won't have the Sub. Edited 2025-01-10 12:27 by phil99 |
||||
digger72 Newbie ![]() Joined: 07/02/2021 Location: GermanyPosts: 4 |
Thanks for your help. @phil99 I will experiment a little with your suggestion. Thank you. GEOS for the C64 is a good example of the principle. A basic application runs and within this application you can start PAINT, WRITE or any other sub-programme. |
||||
Mixtel90![]() Guru ![]() Joined: 05/10/2019 Location: United KingdomPosts: 7865 |
The C64 (as most home computers) has its editor and BASIC interpreter in ROM at all times and the user program space is all RAM area. This makes such tricks relatively easy. The RAMTOP address is stored in RAM, so you can change that to move the top of the RAM area lower. BASIC will still run as its variables are usually stored at RAMTOP-some figure or other. It will just have less user space to run in. The empty RAM area can then be loaded with a second program. MMBasic does not work in this way. The editor is effectively a transient program that uses the variables area to store the program being edited in plain ASCII. After editing the program is pre-processed to handle #INCLUDE and tokenize it before it can be run. The plain ASCII copy of the program is replaced by the variables. Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
thwill![]() Guru ![]() Joined: 16/09/2019 Location: United KingdomPosts: 4302 |
Interesting Mick, I've never thought about it before, but I guess that is how it might work on '80s micro-computers. MMBasic could have done it that way too, but it doesn't and I don't see that changing ever. Should anyone care the approach I'm currently using where a "shell" program want to RUN a "child" program and then be returned to is for the shell program to write its name into a file called "A:/.mmbasic-shell" and then pass the command line argument --shell to the "child" program. On exit the "child" checks MM.CMDLINE$ and if --shell is present will RUN the "shell" program. This doesn't address restoring the state of the "shell" program which should I feel it necessary I would achieve through writing/reading state to files. Note that @matherp the enhanced END command in the very latest PicoMite versions to provide an alternative method of returning to a shell (by running a command on program exit), but it isn't available on the CMM2 or MMB4L (yet) so I chose not to make use of it. Also there are issues if/when the shell is run from FLASH in which case you don't have a value for MM.INFO(CURRENT) to write into ".mmbasic-shell". ' Reads the '.mmbasic-shell' file. ' ' @param exist% If 1 then ERROR if file does not exist, otherwise return empty string. ' @param fnbr% File number to use for accessing the file, if unspecified/0 then uses #9. ' @return The contents of the first line of the file. Function sys.read_shell_file$(exist%, fnbr%) Const f$ = sys.HOME$() + "/.mmbasic-shell" If Not exist% And Not Mm.Info(Exists f$) Then Exit Function Const _fnbr% = Choice(fnbr%, fnbr%, 9) Open f$ For Input As _fnbr% Line Input #_fnbr%, sys.read_shell_file$ Close _fnbr% End Function ' Writes the '.mmbasic-shell' file for later reading by sys.run_shell(). ' ' @param s$ Contents to write to the file, if empty then writes path of current program. ' @param fnbr% File number to use for accessing the file, if unspecified/0 then uses #9. Sub sys.write_shell_file(s$, fnbr%) Const f$ = sys.HOME$() + "/.mmbasic-shell" Const _s$ = Choice(s$ = "", Mm.Info(Current), s$) Const _fnbr% = Choice(fnbr%, fnbr%, 9) If sys.read_shell_file$(0, _fnbr%) <> _s$ Then ' Only write if content has changed. Open f$ For Output As _fnbr% Print #_fnbr%, _s$ Close _fnbr% EndIf End Sub ' Runs the program specified by the '.mmbasic-shell' file. ' ' @param fnbr% File number to use for accessing the file, if unspecified/0 then uses #9. Sub sys.run_shell(fnbr%) Const prog$ = sys.read_shell_file$(1, fnbr%) If prog$ <> "" Then Run prog$ End Sub Best wishes, Tom MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
Mixtel90![]() Guru ![]() Joined: 05/10/2019 Location: United KingdomPosts: 7865 |
In Microsoft BASIC and its relatives the program grows upward from the endpoint of the system variables area. That means that the system variables are always at fixed addresses. RAMTOP (or HIMEM? or something like that) on some systems is actually requested when BASIC is started, so that the user has the opportunity to lower it. Program variables are in a stack that works down from HIMEM so the more variables you use the less program area you have. This is where the housekeeping comes in in BASIC. Every so often the system cleans up the variables stack to optimize the program area. If it doesn't do this then eventually the variables will hit the program! Unfortunately this takes a little time to do. MMBasic doesn't need to do this as the variables area is separate from the program space. Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |