For me, making sure our code is structured correctly is an important part of programming. STOS is a very unstructured language; it doesn’t have any kind of function or procedure that we can create to make stand-alone “black box” routines. As a result of this, every variable that is created is global in scope; in other words, if you define a variable, ALL of your program can access that variable.
One of the reasons I created the VS Code STOS extension was to bring at least a little bit of structure to the code structure of STOS. Of course, this is only applicable when viewing the code within the VS Code environment. Once the code is output in the STOS format, it’s pretty ugly, but we really don’t need to worry about that. We can also annotate our code better within VS Code by using the non-transferred comments that only exist in our code editor, and not the final STOS basic file.
So, what we will try to do during this series is create as clean a code set as we can, with lots of comments to explain what is going on for you lovely people that are reading. Hopefully, this will enable you to take the code and do something else with it. I don’t mind what you do with it, but please don’t just distribute it and call it your own. Make sure you create something new and exciting, and all I ask is that you give me a little credit—that’s all.
In this section, we will just do some simple preparations for our main program code. Nothing clever, just the usual housekeeping that we need to do for a STOS program to run how we want.
Creating our Project
This is a simple enough process. Using the command pallet within VS Code, use the function called STOS: The Game Creator: STOS New. This will launch a series of questions about your new STOS project and where to save it on your computer. You can follow detailed instructions on how to do this on the overview page.
Once you’ve got your project created, you will have your main.stos file, which is the main program file that we will be using to write our code.
You will also need to create an area somewhere that either STOS on your ST or your emulator has access to. This is where you will need to copy the project assets and, ultimately, your build.asc file so you can test it out.
When you start a new STOS project in VS Code, you get the initial comments section at the top of the code, just as a reminder that it was me that created the program. So we’re going to remove that and add our first comments as a description of what the project is.
rem *** Manic Miner - STOS Basic Recreation rem *** rem *** Written by Neil Halliday / STOS Coders rem *** June 2023 rem *** rem *** main.stos : main program file
So what’s going on there? Well, the rem command is short for “remark” – in other words, it’s a comment. Having rem on a line of code means that everything after that command is regarded as just a comment and is not any kind of executed code. Even if you had valid code after the rem, it would still be treated as a comment until the next line.
The rem command is a valid STOS command, and is transferred to our final STOS program code, and will be visible within the listing within STOS. We will also be using other types of comments that will not be transferred to STOS, which will be explained later on.
Now that we have our comments done, we will do some basic setup of the screen. This is to setup how STOS controls the screen and switch off some of the STOS elements that are not required when running a full-screen, low-resolution game.
key off : curs off : click off : flash off : mode 0 : hide on : auto back off : anim off : synchro off palette $000,$777,$005,$007,$500,$700,$504,$707,$050,$070,$055,$077,$550,$770,$555,$777
Not crazy code, but let’s explain what each of the commands do.
|key off||Switches off the STOS menu system that is shown at the top of the screen. The one that shows you which function keys do what. The window is only really useful when using the editor, and it is always the first to go. You can switch it back on by using the key on command.|
|curs off||It does exactly what it says on the tin: it switches off the cursor graphic that shows where the text you are going to type appears. Again, this can be turned on using the curs on command.|
|click off||Switches off that horrible sound that is made when you press a key. I think this sound has to be one of the worst keyboard clicks I’ve ever heard, and I spent many years of programming in STOS with the volume down until I was running stuff. As with all the other commands, click on will switch the keyboard click back on (but why would you!?)|
|flash off||Removes the standard colour cycling that is performed on the colour of the cursor graphic. Even though we switched the cursor off before, the colour cycle continues, so we need to switch that off to avoid some of our graphics looking like some LSD-driven fantasy dream. You guessed it, flash on switches it back on.|
|mode 0||Sets our screen mode to low resolution. STOS allows us to use all three of the ST screen modes. 0 = low, 1 = medium, and 2 = high resolutions; however, you cannot use mode 2 unless you are plugged into a high resolution monitor, and even then, you don’t need to because modes 0 and 1 don’t work, so it’s automatically in mode 2.|
|hide on||Makes the mouse pointer invisible. Unfortunately, it doesn’t switch off the mouse interrupt, so moving the mouse around still slows down the running program, but at least we can’t see the arrow. There is a command in the Misty extension by Top Notch that switches the mouse interrupt off to stop that from happening. Now, you would think that you would use hide off to get the mouse pointer back? Sorry, here’s a curve ball that Francois threw us! To get the mouse pointer back, you use the show on command. With both of these commands, you can actually remove the on bit, and then it makes a bit more sense: hide and show. Choose which method you prefer, and then stick to it; neither is right nor wrong.|
|anim off||This makes sure that any STOS sprite animations are switched off. We won’t be using these as they are quite slow; instead, we will be doing something a little bit more interesting to make things run more quickly.|
|synchro off||Switches off the STOS sprite synchronisation interrupt. Anything we can switch off STOS-wise is always a good thing!|
Our second line of code sets the colour palette of the screen. It is simply a list of colours in colour number order, starting with colour 0 (the background and border colour). You don’t have to specify all the colours when you call the command, but you always have to specify them in the correct order. Note: The standard palette command in STOS is not compatible with the STE, so your number ranges here have to conform to the standard ST 512 colour palette numbers ($000 to $777).
Loading Our Assets
What are assets? They are the things that we use within our program, such as sprites and sound effects. They are loaded into STOS memory banks for use during the program’s execution. Lots of programs perform data loads at different points in the game to conserve memory, but as our program is going to be super small anyway, we will just load them upfront. We’re targeting a 512kb ST for this program, so if we start to run out of memory, we can refactor this bit, but we should be fine.
To cater for any refactoring that may be required, we’ll put our loading of assets code in a separate place. We already know that we don’t have procedures within STOS, so we will do the next best thing. We will use a VS Code label and create a subroutine. Now we can call it whenever we want, from wherever we want.
It’s not a perfect way of doing this, but it’s the best we have, and it works well for my needs.
@LoadAssets erase 1 : load "MANIC.MBK",1 return
|@LoadAssets||The identifier that tells the VS Code transpiler that this is a label. As a result, during the conversion to STOS code, the line is converted to a rem line, and a record is made of the line number where it sits. A second conversion pass then happens and replaces anywhere that references the label with the appropriate line number.|
|erase 1||If we already have something in STOS memory bank 1, it will be deleted and space cleared for our new data.|
|load “MANIC.MBK”,1||Loads the MBK (memory bank) file into STOS bank 1. The MANIC.MBK is our STOS Sprite bank, which always resides in bank 1 of STOS.|
|return||Returns to the point where the call to @LoadAssets was made.|
We now need to make a call to our @LoadAssets subroutine. This is done using the STOS gosub command, and we can make a call to that at the beginning of our program. So, we add the line to the top of our program after the call to the palette command.
And that’s it! We’re done for now. We have our screen setup, and we have our assets loaded. If you want, you can transpile the program, load it into STOS and run it. You won’t get much out of it other than a blank screen and an “OK” at the bottom, but at least you know it’s working.
The Game Loop
Probably the single most important element of any game is it’s gameplay loop. This is the section of code that is continually executed during game play and allows us to control, well, everything. If we want to create a game that is as flexible as possible and easy to understand what is going on, I highly recommend making your game loop as simple as possible. I approach this by writing specific sections of code that perform specific game logic tasks. With a language like STOS, this can become quite messy, but using the VS Code development environment really helps us here. So, let’s create our game loop.
repeat gosub @WaitVBL until false
Pretty simple right? Well, yeah it will be at this point in time, but as you can see, I’m making a call to the @WaitVBL subroutine. By using this technique, we can make our game loop very simple and add new subroutines and call them from our game loop without making things ugly in terms of code. So, what’s going on in our game loop?
|repeat||The repeat command forms part of a repeat/until loop, which can be simply explained as follows… “repeat this next section of code until a certain condition is met.”|
|gosub @WaitVBL||The gosub command tells STOS to “goto” a “subroutine” – in this case, the @WaitVBL subroutine. Normally in STOS basic, the @WaitVBL section would be a line number; but because we are working in VS Code, the transplier will automatically convert @WaitVBL in to the relevant line number for us. This makes our code much simpler to read.|
Note: All subroutines must terminate with a return command so that STOS can go back to where it called it from.
|until false||This is an interesting one. Here we are specifying the condition for the loop to stop. Every condition within the basic language equates to either true or false. This could be something like (1 = 1), which equates to true; (1 = 0) would always equate to false. Because we are just using false, there is no condition; it’s just always false. Therefore, our loop will just go on forever. In STOS true is represented by the number -1, and false represented by the number 0.|
We will amend this statement later in our development cycle because we will need to take into account a game-over scenario.
Now we need to put the code in place for our @WaitVBL subroutine.
@WaitVBL screen swap : doke $ff8240,$222 : wait vbl : doke $ff8240,$000 return
|screen swap||Swaps the addresses of the physical and logical screens. This is also called “double buffering“. The idea behind this is that you display all your graphics off screen, and when the time is right, you swap the screen to show what has just been displayed. Then, while that display is showing, you draw your new updates on the hidden screen, and again swap it to show your new display when you are done. This prevents your objects from being displayed as you are drawing them and prevents flicker on the screen. Good eh?|
|doke $ff8240,$222||Eh? Er? What? Just what is going on here?|
Well, it’s quite simple to explain. Memory address $ff8240 is where the ST reads the value that represents what colour 0 is set to (the border, or background). By doking a value (doke is when we want to store a 16-bit value, also known as a word, into a memory address) we are setting the border to $222, which is a dark grey colour. You’ll see why we do this in a second.
|wait vbl||This command forces STOS to wait for the next vertical blank (VBL). In other words, it stops the execution of any other code until the vertical blank returns to the top of the screen. The use of the wait vbl command is what ensures we can create a consistent speed of game play and reduce flicker.|
|doke $ff8240,$000||As with the other doke command, we are directly setting the border colour, but this time we are setting it back to black.|
So why do we change the colour of the border before and after the wait vbl command? Well, this is a clever little trick that let’s us see how quickly our game is running. The border will be black before all our routines are called, and it will then turn grey for the amount of time that it takes for the vertical blank to return to the top of the screen. The larger the section of black, the more CPU time is being used to perform our code.
The Atari ST in low and medium resolutions run at either 50hz or 60hz depending on where you are located in the world. Therefore, the VBL returns to the top of the screen either 50 or 60 times per second. In other words, the screen redraws at 50 or 60 frames per second. Most games on the ST run at half this speed, and it’s quite rare to actually find a game that runs at full frame rate on a standard ST. Our aim is to make sure everything runs in a single VBL; however, this is particularly hard to achieve when writing programs in STOS. But let’s see what we can do. If your area flashes a lot, it’s likely you are over a single VBL, whereas if the grey colour is solid – good job, you’re running at 50/60 frames per second!
That’s All For Today
That’s all that we are going to cover in this section. Join us in episode three, where we will look at getting Miner Willy to walk and jump.