Lesson 3: Virtual Worlds and PlayfieldsTopics:
Load a different virtual world (just like loading another playfield in bB).
Edit virtual worlds (like editing a playfield with bB).
Set pixels anywhere in the virtual world
Check pixel status and flip them
Pan the camera to any part of the virtual world
Scrolling around the virtual world using Assembly or bB. Load a different virtual world
If you scroll down further in the initialisation section you will see the call to load the large virtual world into RAM:
Note: The “Superchip” used is the double superchip
, or CBS RAM which sports 256 bytes instead of 128; this is important because the large virtual worlds are 240 bytes in size!
There are two other predefined virtual worlds that can be loaded with these descriptive calls:CallBank1ToLoadCBSRAMwithLargeBitmapSayingREADYPLAYER1
Just edit the call in the initialisation section to load one of these other virtual worlds instead.Editing Virtual Worlds
The virtual worlds are in WYSIWYG format similar to a bB playfield only “1” denotes the pixel is on and “0” means it’s off. Here is the first one, the other two are located below:
There are twenty rows of 96 pixels, however the first four pixels are not visible for an effective virtual world resolution of 92x20 with a 20x10 playfield window that can be panned anywhere within.
Note that the “%” is just a prefix for the Assembler that means we are using binary and can be ignored for now (we will cover it later) since using binary to construct a bitmap image is already intuitive and visual; you can see the corner of the larger virtual world outlined above and if you look around the image you will see the word Atari
and the other designs.
Play around with changing and customising the bitmap image.Adding more virtual worlds
When we get to the lesson on bank switching (optional), you will be able to add more virtual worlds as they live in the second bank. For now you have three virtual worlds you can customise.Building dynamic virtual worlds
It is possible to have an algorithm construct the virtual world just like with bB playfields; samples should be easily adaptable as follows.Setting pixels on the virtual world
are the x and y coordinate variables for the virtual world. getbitstatus
is the function to call.
As this is a complex function, an argument is also passed
in the Accumulator
0 – Invert the bit; off if it was on, and on if it was off.
1 – Always turn the bit on, and pass back its previous state in the Accumulator.
This gives us the ability to set, invert or poll specific pixels anywhere in the large virtual world.Setting a pixel
Here’s an example setting pixel 1,1. Add this code to the game loop
section of our latest Assembly file, asdktutr3.asm:;---------Set pixel 1,1 on the Virtual Worldlda #1sta bitx sta bitylda #1; argument to pass: turn bit onjsr getbitstatus
Compile your code and launch it in Stella to check; you should see that pixel 1,1 has been set:
Inverting a pixel instead of setting it done by passing a zero in the Accumulator
instead of a 1, then the pixel will be flipped from whatever it’s previous state had been. Poling pixels
Note that the function call returned the previous status of the bit in the Accumulator
, it was off in this case so the value is zero; if we had wanted to know the status of the bit but didn’t want to set it we would simply set the pixel as per our example to get it’s status - if the status came back as previously clear, we could just call the function again to flip the pixel back off (the poling function is built from stacking a set with a possible invert). Here’s the example:;---------check the status of a pixel on the virtual world:; --------(using set and invert functions);---------Set pixel 1,1 on the Virtual World lda #1 sta bitx sta bity lda #1; argument to pass: turn bit on jsr getbitstatus ; set pixel 1,1;------------------------;--- the accumulator now has the previous status of the bit (0 or 1) sta b ;store bit status in var b to work with it ;-- restore previous bit status with a 2nd call: jsr getbitstatus ; invert pixel 1,1 OR set pixel 1,1 (depending upon argument) ;-------------------------
As you can see, we’ve built the poling function by just repeating the dual purpose set/flip function call again after first storing the target bit’s status in a variable.Pan the Camera to any part of the virtual world
For this example, we will slide the playfield over the Atari text in the large virtual world by setting the camera to position 42,9 in the virtual world:
Here’s what’s gong on with the purple code:BITIndex
is the x position variable for the camera, we’ve set it to 42.
The camera y position is a bit trickier, we are using an offset (BYTErowoffset
) we increase by 12 for each y position increment, which is what the loop does; we could have done the calculation ourselves as well.
Note: There is a “hidden” Assembly instruction in the loop!
DEX (decrement X) also does an automatic compare against zero:“CPX #0”
This hidden comparison allows the BNE (branch if <>) to keep looping the code until X reaches zero.Scrolling around the virtual world
For the next example, we’ll use the joystick controllers to scroll the camera around the virtual world! And we’ll use bB to help us build the Assembly code.
Using what we know to calculate BITIndex and BYTErowoffset this is pretty easy; we set up some aliases so we can use the ASDK variables for the camera and here we go:
Compile your bB and copy the Assembly output block into the game loop section of the ASDK just as we did before:
Now compile your Assembly and test it in Stella! You should notice two things – you can’t scroll quite all the way to the left, there was a bug in the bB code we converted, it should have been “>0” not “>1”. I’ve fixed it in the Assembly output above. I left the other bug in because it allows us to scroll down past the edge of the virtual world and view other memory areas, some of which is active RAM.
Let’s take a look at the three new Assembly instructions the compiler generated:“bit SWCHA” “BMI”
– branch if minus (if bit 7 is set)“BVS”
– branch if overflow bit is set
The bit instruction is examining the bits on the joystick port SWCHA
and the two new branch instructions act on the different bits that are set when you move the joystick; we’re going to be reviewing bitwise operations later but for now you can reuse this block of Assembly like a template to hook up the joystick for your games.Chapter Review
You now know Assembly well enough to write loops, code game logic, manipulate variables and marshal high level objects; start building some demo’s and games and you will get even better at it for the simple fact that you are actually using it!
There are many paths to learning Assembly but we learn best by doing, and achieving enlightenment on the gamegrid is the most fun