Data is also cool

I had created (copied) my first lms program. It was a small script with a few instructions. There was no branching or states or anything. So I figured the next step should be a bit more complex. I didn’t want to take on too much at once so I figured I could send a variable as parameter to UI_DRAW TEXT. So I had to create a variable. I had looked at other lms sources and had a vague idea of how it could be done, but I had to go back and look at the other scripts.

While looking into it I found what seems to be 5 different data types. DATA8, DATA16, DATA32, DATAF and DATAS. 8 bit, 16 bit and 32 bit signed (I assume) integers, a float which is probably 32 bit, and a string.

Defining a variable was as easy as adding “DATA8 VariableName” in the code. The tricky part was to match the variable type to the in parameter of the print function. I’m only assuming that the type have to match exactly, I doubt there will be any conversion done automatically.

So I had created my first variable. Assigning a value to it was a function called MOVE8_8( x, y ) where y gets the value of x, MOVE8_8( 3, VariableName ) is equivalent to VariableName = 3; in C. It was somewhere around this point I realized the syntax is similar to assembler. In X86 assembler you write “mov ax, bx” to assign the value of register bx into register ax. In ARM assembly you would write “mov r0, #3” to assign the value 3 to the register r0. And, the syntax that is the most similar, is the 68000 where you would type “move.b #3, a0” if you want to assign the byte value 3 to register a0.

Now I had my initialized variable and I was setting up the loop. Loops in LMS are also identical to most assembler syntax. You just insert your label anywhere in the code and end it with a : sign, so to create a label called MyLabel you would write MyLabel: and you would be able to jump to it. I also found the ADD8_8( x, y, z ) which is equivalent to z=x+y and I passed my variable into the print function. At the end of the loop I also wanted to reset my variable if it had become too big because I didn’t know how the VM would react if I tried to print text that would go outside the screen, so that was added.

I could simply jump back to my label, but doing so would mean there was no way out of the program. I still don’t know what would happen if I create a program that doesn’t have an exit of its own, if the VM always let the user exit programs with a certain key press, or if each program must have a way to exit gracefully. In any case I wanted to exit gracefully so I looked into the input functions available.

The function I had used in my hello world had a built in loop and would stall until the button was pressed, but I wanted to once per iteration check the status of a key and depending on the status either loop again or exit the loop. I found the function UI_BUTTON( EventType, Button, Status ) that would poll the key Button for the event type EventType and store it’s state in Status.

Being used to assembler I looked for a compare-function that would store the result in a flag internal to the VM and then do a conditional branch, so I found CP_GTEQ8( x, y, status ) and JR_FALSE( Status, Label ). Together they composed the conditional part of my loop and the program was done! Would it compile though?

I saved it to a new file called Vaxholm to keep a record of what I had done. (I was on a boat cruise while doing this so I named my three next experiments after which island I was on at the time) I had no idea what to expect from the compiler if something was wrong, so I ran it on my new app and once again I was informed of the size of the binary. I transferred the binary and started it and there it was, my first scrolling text on the brick!

And this is the source code:

vmthread  MAIN
{
  DATA8 Run
  DATA8 DrawX
  DATA8 Flag
  DATA16 DrawX16

  MOVE8_8( 1, Run )
  MOVE8_8( 0, DrawX )

Loop:
  UI_DRAW( FILLWINDOW,0x00,0,0 )                      //  Clear screen
  MOVE8_16( DrawX, DrawX16 )
  UI_DRAW( TEXT,FG_COLOR,DrawX16,50,'hello world' )   //  Write 'hello world' at 10,50 (X,Y)
  UI_DRAW( UPDATE )                                   //  Show the stuff

  ADD8( 1, DrawX, DrawX )                             // DrawX++


  // Check for reset
  CP_GTEQ8( DrawX, 20, Flag )                         // IF DrawX >= 20 THEN Flag=1
  JR_FALSE( Flag, NoResetDrawX )                      // IF Flag==1 THEN JP NoResetDrawX

  // Do reset
  MOVE8_8( 0, DrawX )
NoResetDrawX:

  // Check for key to exit
  UI_BUTTON( SHORTPRESS, BACK_BUTTON, Flag )          // IF backbutton pressed THEN Flag=1
  JR_FALSE( Flag, Loop )                              // IF Flag==1 THEN JR Loop
}

I still need to figure out how to do timing on the brick. I’m hoping there is some form of vsync possible. If there is no opcode called something similar to vsyncwait then perhaps there is some function that does a vsync implicitly, like how setting the color value of a palette index works in qbasic. :) If there is no vsync available I will at least look into the existing timer/sleep functions.

Leave a Reply