Using The Assembler 04

By Richard Dimond

Originally published in EUG #21

I hope members are following me all right and have been able to create some characters. I will now show you how to move these about the screen and select menu options.

But first, I must explain about where M/code can be stored - as we shall need more room from now as page &C is used for the characters. Loading M/code to &900 is useful for short routines and utilities but not for a game.

There are three other options -

  1. Using a DIM statement to reserve space above TOP
  2. Lowering HIMEM to reserve space above this
  3. Raising PAGE to reverve space below

Options 2 and 3 are best left for a completed game which is fully M/code but for the present I shall use option 1 as this is easier to set up.

The disadvantage is that the M/code has to be assembled each time as the area used varies as the assembler listing lengthens.

I have re-written the assembler listing for this method and included all the subroutines so far. These have been revised to make them clearer and include the variables as explained last time.

I have put the data for the character on page 94 of the manual for those who have not created one yet. Also I have put a basic main loop in so that the program will run and you can move the character around though, since M/code is very fast, you will not have much control yet.


This routine uses the OS subroutine OSBYTE. This is used for the M/code equivalent of the *FX calls.

Register A is loaded with the value of the FX call and registers X & Y the parameters needed. Thus:

is the equivalent of *FX15,0 used for clearing the buffers.

For reading the keys, we use OSBYTE with register A loaded with 129. Y is loaded with &FF and X with the negative INKEY value of the key. With this routine, the Carry flag is clear until the key is pressed and so a test on the Carry flag will show whether or not the key is pressed.

I have put the subroutine 'move' in for using keys Z, X, : & / for Left, Right, Up and Down. Thus for the Z key:

         .lt LDA#129:LDX#&9E:LDY#&FF:JSRosbyte                \ INKEY-98
For the present, the movement subroutines simply increase or decrease the co-ordinates for printing the character. They will need to be added to later.

As I said, it is too fast to control so I have added the subroutine delay:

         .delay PHA:TXA:PHA:TYA:PHA:     \ save register values on stack
         LDXspeed:.xloop :LDY#255:.yloop DEY:BNEyloop:DEX:BNExloop:
         PLA:TAY:PLA:TAX:PLA:RTS               \ restore register values
The subroutine will need to be called in the main loop by:
         320 JSRdelay
         350 JSRdelay
It is entered twice so that the character flashes evenly.

The value entered in speed can be varied to alter the speed. Also, for longer delays, you can add some NOPs into the loops. This opcode does not do anything, as its name suggests, but does cause a little delay in the operation of the code.

While it is only really necessary to save the values in X and Y registers in this routine, I have included the 3 to illustrate the use of the stack. This is often done in this way. Note that the three values must be PULLed off in reverse order.

I suggest you should experiment with this and also try changing the Mode. I have used Mode 4. If you use Mode 2 or 5, you will need to alter the 39 in PROCright to 19 to prevent the character moving off the screen.

At present, to stop the program you need to press BREAK. It is best to provide for pressing ESCAPE and this can be done by using:

         LDA#129:LDX#&8F:LDY#&FF:JSRosbyte           \ INKEY-113  ESCAPE
         BCCcont:RTS                                   \ Return to BASIC
This must be in the main loop since, if it were in a subroutine, it would simply end the routine and not return to BASIC.

Making Choices

Whether it is to select from a menu or simply to answer a yes or no question, we shall need to make our choice.

For this we use the OS routine OSRDCH (&FFE0).

This routine stops the program and waits for a key to be pressed. It will put the ASC value of the key into register A.

If ESCAPE is pressed, the Carry flag is set so a test of this flag can be used for breaking out of the program and returning to BASIC:

         .rdch      JSRosrdch
                    RTS                               \  Return to BASIC
         .cont      (rest of program)
For answering a question add:
                    CMP#ASC"Y":BEQ yes
                    CMP#ASC"N":BEQ no
         .yes       JSR instructions      \ (or whatever)
         .no        (rest of program)
This can be extended or altered to any keys.

You can select three or more choices by a series of letters or numbers using:

         .rdch      JSRosrdch
                    CMP#ASC"1":BCCrdch    \ back if <ASC"1"
                    CMP#ASC"4":BCSdrch    \ back if >ASC"3"
         .choice1   JSRoption1:JMPrep
         .rep       (rest of program)
The speed of the game can be selected by:
         200    .spset     JSRosrdch
                ASL A:ASL A:ASL A:ASL A
Enter this in the program before the main loop.

The keys 1 to 3 are selected again then 48 is subtracted from the ASC value so that the values given are 1, 2 and 3. The 4 ASL A shift the bytes left four times, this multiplies by two each time and thus gives values for speed of 16, 32 and 48.

Note that the Carry flag must be set before the subtraction.

I hope my articles are giving some members ideas for writing programs in M/code. If there are any problems or questions so far, I am always happy to try to help. As I said last time, the more we experiment, the more we learn.

I am hoping to show how to set up a screen and how they may be loaded next time.

Richard Dimond, EUG #21