Better Launch Code

This tutorial builds off of the last, improving our launch code.

The first order of business is to actually start the engine. As you know this is done by setting the throttle to 100%, and staging.

In order to set the throttle, we need to introduce how to access variables in KASM.

Throttle

Variables exist in a scope, which has an ID, which can be set up by two instructions:

  • bscp - Begin scope
  • escp - End scope

By default kOS creates a global variable scope, whose ID is 0. If we want to make variables in our "main function" scope, the scope ID is incremented, for example to create our variable scope will be 1:

bscp 1, 0

... our code

escp 1

The first operand to bscp is the new scope ID, and the second is supposed to be the "parent ID", or the scope that this scope is in.

The operand to escp is the number of scopes that we are ending. We have only created one variable scope, so the operand here is 1. This removes any variables that were declared in that scope.

If you know C-style languages, or even just KerboScript, you can think of bscp as a { and escp as a }

Now that we have that, in order to set the throttle, all we have to do is set the value of a variable named throttle. Variables in kOS are prefixed with the $ character, so the name would be $throttle

In order to store a value on the stack to a variable, there is the sto instruction, which stands for store.

So in order to set the throttle, the code is:

bscp 1, 0

...

push 1.0 ; The value we want the throttle to be
sto "$throttle"

... other code

escp 1

Staging

When you write the KS code STAGE., it actually just calls a built-in function: stage()

So this is the code you have to write to stage in KASM:

push @
call #, "stage()"
pop

Steering

We need to do the equivalent of KerboScript SET STEERING TO UP.

Once again, this is done using global variables.

The UP is actually a global variable that contains a rotation value that is straight up.

Steering is similar to throttle in that there is a global variable named $steering that we set to the desired rotation.

Therefore setting the steering to up can be performed using the following code:

push "$up"
sto "$steering"

Note that push-ing a variable puts the variable's value on the stack

Waiting

If the code were to set the throttle, set the steering, and then end, kOS would tell the throttle and steering to go back to normal. Therefore in order to make them stay, we need the program to not end.

This can be performed with an infinite loop like so:

.infinte:
    push 0
    wait
    jmp .infinte

Note the use of push 0 and wait. As noted in the kOS documentation, if you just have an infinite loop it can slow down your game, and use more electric charge. Therefore we wait for 0 seconds, to provide a small but unnoticable delay.

This would work perfectly fine, but to be a little more sophisticated, we will follow more along with the kOS tutorial and wait until we are above 70,000 m.

Similar to throttle, steering, and up, the SHIP variable it self is just a global variable named $ship.

In KerboScript in order to get the ship's altitude, one would write: SHIP:ALTITUDE

In order to do the :, we will use an instruction called gmb, which stands for "get member"

To get the ship's altitude, we would write:

push "$ship"
gmb "altitude"

To check this in a loop against 70,000 we would write:

.altitude_loop:
    push 0              ; Wait 0 seconds to provide a little delay
    wait
    push "$ship"
    gmb "altitude"      ; SHIP:ALTITUDE
    push 70000          ; > 70,000
    cgt                 ; Actually performs the comparison
    bfa .altitude_loop  ; If it isn't 70,000 yet, loop again

Putting it all together

Combining all of the code we have written so far together, the result would be:

.macro CLEARSCREEN
    push @
    call #, "clearscreen()"
    pop
.endmacro

.macro PRINT
    push @
    swap
    call #, "print()"
    pop
.endmacro

.global _start

.func
_start:
    bscp 1, 0

    CLEARSCREEN

    ; Do the countdown
    push "Counting down:"
    PRINT
    push 10
    .countdown_loop:
	dup
	push 0
	clt
	btr .countdown_end
	dup
	push "..."
	swap
	add
	PRINT
	pushv 1
	wait
	push 1
	sub
	jmp .countdown_loop
    .countdown_end:

    ; Set the throttle
    push 1.0
    sto "$throttle"

    ; Set steering
    push "$up"
    sto "$steering"

    ; Stage
    push @
    call #, "stage()"
    pop

    ; Wait to reach 70km

    .altitude_loop:
	push 0              ; Wait 0 seconds to provide a little delay
	wait
	push "$ship"
	gmb "altitude"      ; SHIP:ALTITUDE
	push 70000          ; > 70,000
	cgt                 ; Actually performs the comparison
	bfa .altitude_loop  ; If it isn't 70,000 yet, loop again

    escp 1
    eop