• Please review our updated Terms and Rules here

C64 BASIC: Automated LOADs - HELP!

Raven

Veteran Member
Joined
Mar 7, 2009
Messages
2,752
Location
DE, USA..
I am writting a bootstrapper, for lack of a better word, for CommoDOS (my new project). I made the first file on disk be "LOADER", which collects info and then runs "COMMODOS WEDGE". That runs, and then loads "COMMODOS RAMDISK". That runs, and then loads "1764DOS" (will be later called "COMMODOS").

The only problem is that this isn't working so well. From a clean boot, I type 'LOAD "*",8', and the loader is put into memory. I type "RUN". It executes, asking me what drive number it is in - I tell it "8", and it proceeds to load the wedge into memory. I did this using the same commands I would use in BASIC, but with variables so the user is prompted for which disk the program is on, i.e.,

INPUT "WHAT DRIVE IS THIS";D
LOAD "COMMODOS WEDGE",D
RUN

It errors out on one of the first few lines, and when I list that line something is always weird (a character or two from another line is in that line, and some of it is missing). If I list the whole program, I find that only five lines or so are there, the rest isn't loaded, thus the error. If I load the program with the exact same commands from BASIC myself, it works fine. I can only assume that LOAD or RUN behave differently when a program calls them than when a user does.

Please explain this difference, or any ideas or workarounds you may have.

Thank you!

Edit:
If the complete source of any of these files would help you help me, just ask and I'll xfer them over using my XM cable and post them in a pastebin or on here.
 
Am I wasting my time asking C64 BASIC questions here? Does anybody here program in it? Or should I go find a C64 BASIC forum or something (didn't find one so far..)?
 
Am I wasting my time asking C64 BASIC questions here? Does anybody here program in it? Or should I go find a C64 BASIC forum or something (didn't find one so far..)?
Sounds like a plan; maybe the folks on here just don't want to get involved in your project...

I'd certainly expect that simply loading another program on top of the currently running program just might cause a problem or two...
 
My assumption was that it would replace the current program and swap control to the new one, but maybe I was understanding incorrectly how load works. Anywho thanks for replying. :p
 
I think what you want to do is something like this:

Code:
10 INPUT"WHAT DRIVE IS THIS";D
15 PRINT"{CLR}{4 SPC}";CHR$(34);"COMMODOS WEDGE";CHR$(34);",";D
20 POKE631,19:POKE632,131:POKE198,2

It would prepare the screen for the LOAD command at given device. The last thing it does is to fill the keyboard buffer with HOME and the special SHIFT+RUN/STOP character (131) which normally loads and runs a program from tape, but in this case will load and execute the file you specified.

The difference from your approach is that the LOAD happens after the program is finished, and the next part gets run from direct mode instead of the program overwriting itself with another one. Your approach works if you e.g. load machine code or graphics parts into another memory area than your program is running in, but it would also cause your main program to restart everytime a LOAD has completed. It can be solved by assigning variables or POKE memory addresses to keep as a flag and GOTO a different line number:

Code:
10 IFPEEK(49152)=77THEN20
12 IFPEEK(49152)=88THEN25
15 POKE49152,77:LOAD"BINARY",8,1
20 POKE49152,88:LOAD"GRAPHICS",8,1
25 SYS16384

Give or take that the program may not work as intended, but I think you get the idea.

Besides, I will give you one more hint: PEEK(186) contains the device number of the last used drive. Thus you would not need INPUT unless you want the user to specifically boot from a different device than the bootstrapper did.
 
I think what you want to do is something like this:

Code:
10 INPUT"WHAT DRIVE IS THIS";D
15 PRINT"{CLR}{4 SPC}";CHR$(34);"COMMODOS WEDGE";CHR$(34);",";D
20 POKE631,19:POKE632,131:POKE198,2

It would prepare the screen for the LOAD command at given device. The last thing it does is to fill the keyboard buffer with HOME and the special SHIFT+RUN/STOP character (131) which normally loads and runs a program from tape, but in this case will load and execute the file you specified.

The difference from your approach is that the LOAD happens after the program is finished, and the next part gets run from direct mode instead of the program overwriting itself with another one. Your approach works if you e.g. load machine code or graphics parts into another memory area than your program is running in, but it would also cause your main program to restart everytime a LOAD has completed. It can be solved by assigning variables or POKE memory addresses to keep as a flag and GOTO a different line number:

Code:
10 IFPEEK(49152)=77THEN20
12 IFPEEK(49152)=88THEN25
15 POKE49152,77:LOAD"BINARY",8,1
20 POKE49152,88:LOAD"GRAPHICS",8,1
25 SYS16384

Give or take that the program may not work as intended, but I think you get the idea.

Besides, I will give you one more hint: PEEK(186) contains the device number of the last used drive. Thus you would not need INPUT unless you want the user to specifically boot from a different device than the bootstrapper did.

Ah that's a hell of a tip - will make modifying all sorts of loaders (mine and otherwise) much easier. I have lots of old multi-game disks with custom menus in BASIC that are designed to only run from 8 and I have two drives on my main C64.

Thanks much, I'll start working on CommoDOS in the next few days (maybe tonight) and will try to work something out with the material you've given me.

By the way, I have several books on BASIC for 80s computers, but none specifically for the C64 (except the official ones, but they aren't too comprehensive). Do you know a good online source, and failing that, a good book I could look for that explains the caviats of the C64 BASIC, covering things like what characters can cause the machine to do what, where different SYS, PEEKS, and POKES can be used to do different operations, etc.? Or must one just read the ROM disassembly and learn the hard way?

Edit:

*smacks himself in the face*

Gah, I forgot after receiving so many old Mac books one time, that in with all of those Mac books happened to be a few Commodore books, including troubleshooting books, and one labeled "How to Program Your Commodore 64: Basic for Beginners". Being a C64-specific book, it should have a lot of those caveats I was referring to earlier.

*puts book on his C64 monitor so he remembers to use it as reference*

Edit 2:

*finds his Programmer's reference manual* that'll help some.. lol I'd been working off of the user guide and non-C64-specific docs.
 
Last edited:
I've hit a snag. After working through the code you wrote and figuring out how it worked and how to adapt it into my code properly I eventually got it to work, loading the next program from the loader without issues. However, when the next program loads, the "last used drive" peek(186) routine returns 1, making the next disk routines try to call the datasette instead of the disk drive that it's being run from. I realize that the way you coded it it's using the load button's method of loading things, but I think that attached to that, even with the haxy method you used to use it to load from a file (that I don't properly comprehend the workings of) still changes the last used drive to 1. This could be bypassed by sticking a value in memory somewhere and then restoring the value by poking 186 with the peeked value at wherever. I'm not familiar with the memory layout yet, though, or the poke command, so could you let me know where'd be safe to store it? I'll then read up on the poke command and write up a fix.

Thanks.
 
It sounds strange. The operating system should not change the value of PEEK(186) unless you actually used a different drive. I just tried the following in the emulator:

LOADER1.PRG
10 PRINT"{CLR}{4 SPC}";CHR$(34);"LOADER2";CHR$(34);",";PEEK(186)
15 POKE631,19:pOKE632,131:pOKE198,2

LOADER2.PRG
10 PRINT"{CLR}{4 SPC}";CHR$(34);"LOADER3";CHR$(34);",";PEEK(186)
15 POKE631,19:pOKE632,131:pOKE198,2

LOADER3.PRG
10 PRINT"HELLO WORLD"
20 GOTO10

When I execute LOADER1, it only takes a second to go through LOADER2 and LOADER3 to start the "main" program. You may need to upload more of your code to determine exactly what is going wrong.
 
My first program, LOADER, pretty much just consists of the load routine you wrote for me. If I execute that it starts the second program, which prints a banner and immediately complains the second it hits a load statement (I didn't retool it to use your code yet, but I did replace the original inputs with PEEK(186)s) to press play on the tape.

I'll grab the code and stick it up here when I can if this wasn't enough info.

Can you explain what this line does?
15 POKE631,19:pOKE632,131:pOKE198,2

I get that the POKE632,131 is putting character 131 onto the screen and that it's the LOAD character, but I'm not sure how this works, or what the other two POKES do.
 
POKE631,19 adds a HOME keypress to the keyboard buffer
POKE632,131 adds the SHIFT + RUN/STOP keypress to the buffer
POKE198,2 says there are exactly two keypresses in the buffer to execute

The buffer can hold .. uh, eight or ten keypresses at a time. When the program is finished, Basic will check if there are any keypresses to handle.
 
POKE631,19 adds a HOME keypress to the keyboard buffer
POKE632,131 adds the SHIFT + RUN/STOP keypress to the buffer
POKE198,2 says there are exactly two keypresses in the buffer to execute

The buffer can hold .. uh, eight or ten keypresses at a time. When the program is finished, Basic will check if there are any keypresses to handle.

It's ten, I do know some stuff, lol. :D Thanks for the explanation.
 
Back
Top