Introduction
This is a programming language similar to assembly or BASIC. This language is made with vanilla javascript, and quite beginner friendly. There is a console for character IO and a basic 40x30 pixel canvas for displaying 16 color graphics.
Types
For numbers this language only supports integers. You can store them inside constants,
registers or in the memory.
The language also has strings, but only as literals. To define a string you have to use double quotes like this: "string"
To store user input strings we use the memory, and store the characters by their index. (See also the Characters example)
For arrays you can use the memory. This is basically a fixed size array with a length of 512
Example for types:
- A constant declaration "a" with value 50
- Storing the value: 5 to a register with index 1
- saving the value 64 to the memory at address 12
const a 50
op R1 = 5
save 12 64
More on the commands later.
Memory and Registers
There are 2 types of data storage, the memory (with addresses, from 0 to 511) and the registers (fixed from R0 to R63) To save a value to the memory you have to use one of the following keywords: save, save_str, load
To load a value to a register you can use the op keyword.
Some keywords use the memory as input, for example print_str
Video memory
This is a special memory used for displaying data to the graphic output. You can use the display_color keyword to display a 40x30 pixel area of the video memory to the graphical output. This window can be moved around using the set_scroll keyword. The total size of the video memory is 80x60 pixels. There is an option toswitch in to high-res mode with the zoom keyword. The colors are stored as a number, representing a palette index. (See also Palette indexes)
Comments
As in every language, there are comments. Comments are started with the "#" character and span to the end of line.
print_txt "" 1 #This is an end-of-line comment
#This is a full-line comment
Math
SIN [num] [reg]
This function will compute the value of sin(num1)*100, rounds it to the nearest integer and puts it to reg. So the minimum value it can produce is -100 and the maximum is 100.
sin 30 R1
sin R2 R3
Parameters
- num: The number whose sine is being calculated
- reg: The output register, where the value will be copied to
COS [num] [reg]
This function will compute the value of cos(num1)*100, rounds it to the nearest integer and puts it to reg. So the minimum value it can produce is -100 and the maximum is 100
cos 14 R54
cos R0 R1
Parameters
- num: The number whose cosine is being calculated
- reg: The output register, where the value will be copied to
ABS [num] [reg]
This function gets the absolute value of num and puts the result to the given register
Example:
op R0 = -10
abs R0 R0
#Expected output: R0 = 10
Parameters
- num: The number whose absolute value will be calculated
- reg: The output register, where the value will be copied to
SQRT [num] [reg]
This function calculates the square root of num and puts the result to the given register. The values will be rounded to the nearest integer, and if num < 0 then the the value in reg will be 0.
Example:
op R0 = 4
sqrt R0 R1
#Expected output: R0 = 4, R1 = 2
Parameters
- num1: The number whose square toot will be calculated
- reg: The output register, where the value will be copied to
SGN [num] [reg]
This function calculates the sign of num puts that in to reg.
- If num is positive: reg will be 1
- If num is zero: reg will be 0
- If num is negative: reg will be -1
Example:
sgn 10 R0
sgn 0 R1
sgn -25 R2
#Expected output:
#R0 = 1
#R1 = 0
#R2 = -1
Parameters
- num1: The number sign will be determined
- reg: The output register, where the value will be copied to
OP [reg] [operand] [num1] [operand] [num2]
This function can be used as a math evaluator. There are 2 scenarios:
- [reg] += [num]
- [reg] = [num1] + [num2]
NOTE: The values will be rounded to the nearest integer!
Example:
op R0 = 1 #first scenario
op R1 += 5 #first scenario
op R2 = R1 + 2 #second scenario
op R3 = 5 / R0 #second scenario
#Expected outputs:
#R0 = 1
#R1 = 5 (0 + 5)
#R2 = 7 (5 + 2)
#R3 = 5 (5 / 1)
The operands in the first scenario
a = b
Sets a to the value of ba += b
Adds b to a (a = a + b)a -= b
Subtracts b from a (a = a - b)a /= b
Divides a by b (a = a / b)a *= b
Multiplies a with b (a = a * b)
Operands in the second scenario
R0 = a + b
Sets R0 to the value of a + b (Addition)R0 = a - b
Sets R0 to the value of a - b (Subtraction)R0 = a / b
Sets R0 to the value of a / b (Division)R0 = a * b
Sets R0 to the value of a * b (Multiplication)R0 = a % b
Sets R0 to the value of a % b (Remainder)
Parameters
- reg: The register where the value of the evaluation will be stored
- num1: A number value can be: number, function, label, register
- num2: A number value can be: number, function, label, register
CLAMP [min] [max] [num] [reg]
This function clamps the value of num between min and max and puts the result to reg
Example:
clamp 0 10 -20 R0
clamp 5 4 10 R1
#Expected output: R0 = 0 R1 = 4
Parameters
- min: The minimum value of num, that is allowed. If smaller, then this value will be set as output
- max: The maximum value of num, that is allowed. If bigger, then this value will be set as output
- num: The number to be checked against the min and max values
- reg: The output register, where the clamped value will be copied to
RND [reg]
This function generates a random number, either 1 or 0 and puts it to reg.
Example:
rnd R0
#Expected output: R0 = 0 or 1
Parameters
- reg: The output register, where the random value will be copied to
RND_RANGE [min] [max] [reg]
This function generates a random value between min and max (both ends included!) and puts the value to reg.
Example:
rnd_range 1 6 R0
print R0 1
#This program simulates
#a 6 sided dice in the
#console
Parameters
- reg: The output register, where the random value will be copied to
Value storage
CONST [name] [value]
This will create a constant with the name [name] and value of [value]. Constants are usually created at
the start of a program
You can not name a constant anything similar to a keyword, register or label!
Example:
const a 2
op R0 = 0 + a
#Expected output: R0 = 2 (0 + 2 = 2)
const foo 32
const bar 16
op R0 = foo - bar
#Expected output: R0 = 16 (32 - 16 = 16)
Parameters
- name: the name of the constant. This CAN NOT BE a keyword, register or label's name!
- value: a number, can't be a register.
LABEL [name]
This will create a const, with the value of the line number it is in
Example:
label first
op R0 = first
#Expected output: R0 = 1
Parameters
- name: The name of the label, to further reference to it. Can be used as a const...
SAVE [addr] [num]
This function will save num to the given address to memory
Example:
const val 3
save 5 10
#Expected output: mem[5] = 10
save 10 val
#Expected output: mem[10] = 3
op R0 = 6
save 12 R0
#Expected output: mem[12] = 6
Parameters
- addr: The address where num will be saved at
- num: The value that will be saved
SAVE_STR [addr_from] [text]
This function will save the character indexes of the given string, starting from addr_from
Example:
save_str 0 "Hello there!"
print_str 0 4 0
#Expected output: Hello
Parameters
- addr_from: The address where the first character will be
- text: The value that will be saved as character ascii indexes
LOAD [addr] [reg]
This function load the value from the given address at memory and copy it to reg
Example:
const val 10
save 1 val
load 1 R0
#Expected output: R0 = 10
op R1 = 6
save 2 R1
load 2 R2
#Expected output: R2 = 6
Parameters
- addr: The address at memory to load from
- reg: The register where the value will be copied
Instructions (flow control)
JUMP [lineNum]
Continues the program from the given line
Example:
const step 1
label loop
op R0 += step
jump loop
#R0 will count upwards forever.
Parameters
- lineNum: The line number where the program will continue from
IF [num1] [condition] [num2] [lineNum]
This will check if num1 and num2 completes the condition and if they do, jumps to the given line
Example:
const numFrom 0
const numTo 2
const step 1
op R0 = numFrom
label loop
print R0 1
#Advance the loopcounter
op R0 += step
#Loop back if R0 is not at numTo
if R0 <= numTo loop
print_txt "Loop ended." 1
#Expected output:
#0
#1
#2
#Loop ended.
The value of R0 will start at numFrom and ends at numTO.
Parameters
- num1: The first part of the condition check
- num2: The second part of the condition check
- condition: The condition to check against. Can be the followings:
- Equals: ==
- NOT Equals: !=
- Smaller than: <
- Greater than: >
- Smaller or equals: <=
- Greater or equals: >=
- lineNum: The line number where the program will jump to if the condition is true
FUNC [name]
Can be used as a number parameter, it runs the code and returns with a value. keep in mind, there is a 256 recursion limit on functions.
Example:
func FprintSomething
#Function body, the RETURN is NEEDED!
return 5
print_txt "Function returned: " 0
print FprintSomething 1
#This will call the function "printSomething"
#and prints the returned value (5)
Parameters
- name: The name of the function
RETURN [num]
Returns with the given value, "replaces" the function name in the call. You must return with something.
IMPORTANT: There can only be 1 function parameter in a line! (op R0 = Fa + Fb) is forbidden...
Example:
func FaddNums
op R2 = R0 + R1
return R2
op R0 = 10
op R1 = 2
print FaddNums 0
#Expected output: (10 + 2) 12
#R0 = 10
#R1 = 2
#R2 = 12
Parameters
- num: A number value to be returned, can be another function...
CALL [name]
It calls the given function, but ignores the return value.
Example:
func FprintDat
print_txt "Function called!" 1
return 0
print_txt "Starting code..." 1
call FprintDat
call FprintDat
print_txt "End" 1
#Expected output:
#Starting code...
#Function called!
#Function called!
#End
Parameters
- name: The name of the function to be called
SLEEP [ms]
When this line is reached, the execution halts for ms milliseconds.
Example:
print_txt "Start!" 1
sleep 1000
print_txt "1 second later..." 1
sleep 500
print_txt "Half a second later..." 1
Parameters
- ms: Expects a positive number value which can't be a function.
Input and Output
INPUT [reg]
Opens a popup input field at the bottom of the console and waits for input, then stores it to the given register. This field only accepts numbers!
Example:
input R0
#if you type in 2: R0 = 2
Parameters
- reg: The register where the input will be stored at
INPUT_STR [addr_start] [max_len]
Opens a popup input field at the bottom of the console and waits for input. Stores the character's ascii indexes in he memory starting from the given address. Maximum input length should be <= max_len.
Example:
input_str 0 5
#Type: apple
load 0 R0
load 1 R1
#R0 = the ascii code of a
#R1 = the ascii code of p
Parameters
- addr_start: The memory address where the first character's index will be
- max_len: Maximum string length you are able to type in
NOTE: The last character's address is: addr_start + max_len - 1
INPUT_KEY [reg]
Puts the last pressed key's code to reg.
The key codes can be found here (scroll a bit)
Bonus, the arrow keys are: 37 - 40 (left, up, right, down)
Example:
label loop
input_key R0
print R0 1
sleep 10
jump loop
#If you press: a
#R0 = 65
Parameters
- reg: The register where the last pressed key's code will be copied to
PRINT [num] [isNewLine]
Prints the given number to the console. If isNewLine is 1 then it makes a new line after it.
Example:
op R0 = 5
print R0 1
print 10 0
print 3 1
#Expected output: 5 and a new line: 103
Parameters
- num: The number to print out
- isNewLine: Whenever the print makes a new line after it's content
PRINT_STR [addr_from] [addr_to] [isNewLine]
Prints the characters from memory from address addr_from until addr_to. If isNewLine is 1 then it makes a new line after it.
Example:
save 0 72
save 1 105
save 2 33
#Storing 3 random numbers
print_str 0 2 0
#Printing out the characters
#corresponding to the random
#numbers in memory.
Parameters
- addr_from: The address of the first character
- addr_to: The address of the last character
- isNewLine: Whenever the print makes a new line after it's content
PRINT_TXT [text] [isNewLine]
Prints the given string to the console.
Example:
print_txt "Give me a number:" 1
input R0
print_txt "The number you gave: " 0
print R0 1
#This code requests a number
#and prints it back
Parameters
- text: The text in double quotes ("string") to print to the console.
- isNewLine: Whenever the print makes a new line after it's content
SET_PIXEL [x] [y] [paletteIndex]
Writes the paletteIndex value to the video memory at the given coordinates.
Example:
set_pixel 0 1 9
set_pixel 1 1 9
set_pixel 1 2 9
display_color
Parameters
- x: The x coordinate of the pixel (from 0 to 79)
- y: The y coordinate of the pixel (from 0 to 59)
- paletteIndex: The palette index, representing a color
NOTE: (0;0): top left, (79;0): top right, (0;59): bottom left, (79;59): bottom right
GET_PIXEL [x] [y] [reg]
Retrieves the paletteIndex from the video memory at the given coordinates, and puts it to reg.
Example:
set_pixel 0 0 1
get_pixel 0 0 R0
#Expected output: R0 = 1
Parameters
- x: The x coordinate of the pixel (from 0 to 79)
- y: The y coordinate of the pixel (from 0 to 59)
- reg: The register where the paletteIndex will be stored at
SET_SCROLL [x] [y]
Scrolls the visible area of the video memory. The coordinates are the top left corner of the viewport
Example:
set_pixel 42 10 9
set_scroll 40 0
display_color
Parameters
- x: The x coordinate of the top left pixel of the viewport (0 - 40)
- y: The y coordinate of the top left pixel of the viewport (0 - 30)
CLEAR [paletteIndex]
Replaces EVERY value in the video memory with paletteIndex
Example:
clear 2
display_color
Parameters
- paletteIndex: The palette index, representing a color
DISPLAY_COLOR
Updates the graphic output, displays the values of the video memory as COLORS. For the effect to be visible, a SLEEP is recommended.
Example:
set_pixel 0 0 9
display_color #Displays the video
#memory as colors
PLAY_SOUND [waveForm] [frequency] [duration] [volume]
Plays the given tone, with [waveForm] waveform, at [frequency] frequeny, for [duration] milliseconds and with [volume] volume.
The function is asynchronous, meaning you can start multiple sounds at once, but a sleep is needed if you want to wait them to finish.
The wavefroms:
- 0: sine
- 1: square
- 2: sawtooth
- 3: triangle
Example song:
const vol 10
const wave 3
play_sound wave 262 250 vol
sleep 250
play_sound wave 262 250 vol
sleep 250
play_sound wave 294 500 vol
sleep 500
play_sound wave 262 500 vol
sleep 500
play_sound wave 349 500 vol
sleep 500
play_sound wave 330 1000 vol
sleep 1000
play_sound wave 262 250 vol
sleep 250
play_sound wave 262 250 vol
sleep 250
play_sound wave 294 500 vol
sleep 500
play_sound wave 262 500 vol
sleep 500
play_sound wave 392 500 vol
sleep 500
play_sound wave 349 1000 vol
sleep 1000
play_sound wave 262 250 vol
sleep 250
play_sound wave 262 250 vol
sleep 250
play_sound wave 523 500 vol
sleep 500
play_sound wave 440 500 vol
sleep 500
play_sound wave 349 500 vol
sleep 500
play_sound wave 330 500 vol
sleep 500
play_sound wave 294 500 vol
sleep 1000
play_sound wave 466 250 vol
sleep 250
play_sound wave 466 250 vol
sleep 250
play_sound wave 440 500 vol
sleep 500
play_sound wave 349 500 vol
sleep 500
play_sound wave 392 500 vol
sleep 500
play_sound wave 349 1000 vol
sleep 1000
Parameters
- waveForm: A number between 0 and 3
- frequency: The frequency of the tone of the played note
- duration: The length of the sound in milliseconds
- volume: A number between 0 and 100 (0 being muted)
Examples
Input and input_str
This program requests your name and age, then stores it to the memory. Keep in mind that the print_str function does not know where the end of the "string" is!
print_str 0 8 1
#So this would print: name####
#where the # represents the unwanted memory garbage.
"loop1" is counting how many characters with a non-zero index are in your name. When it does find the end of your name (detects a character with the index 0), it breaks from the loop, and prints the name's non-zero prart, ignoring the zero part.
Challenges
- Request the first, and last name of the user!
- Make a function for the looped print! (see also Functions example)
print_txt "What is your name?" 1
input_str 0 8 #your name from addr. 0 to 8
print_txt "How old are you?" 1
input R10 #your age in R10
print_txt "" 1
print_txt "Hello " 0
op R5 = 0 #last valid char index
op R63 = 0 #counter
label loop
load R63 R0 #R0: current char index
#break if empty
if R0 == 0 loop_break
op R5 = R63 #save last valid char index
#Advance the loop (max 8 iterations)
op R63 += 1
if R63 < 8 loop
label loop_break
#print the data
print_str 0 R5 0
print_txt "!" 1
print_txt "You are " 0
print R10 0
print_txt " years old! :)" 1
Try it yourself! (Copy and paste it to the editor, and run the program.)
Functions
The program requests a number, and prints out 2 lines: 1 with the length of the number and 1 with half of the length.
The function's "input parameter" is R63, it determines the length of the line. The function uses 2 registers R62 and R63. The line, is drawn with the "#" character and has a new line after it. (See also functions)
NOTE: See the comments above the function? It is a good practice to mark your registers, and add a description to the function.
Challenges
- Make it, so the code prints out the original number, and the halved one.
- Request the divider from the user too!
- Make it so the user can input a character, and the lines will be rendered with that!
#prints an R63 char. long line
func line #(R62, R63)
op R62 = 0
label loopLine
print_txt "#" 0
op R62 += 1
if R62 < R63 loopLine
print_txt "" 1
return 0
print_txt "Give me a number:" 1
input R10 #Input a number (R10)
op R11 = R10 / 2 #half it (R11)
#Draw the line
op R63 = R10
call line
#Draw the halved line
op R63 = R11
call line
Try it yourself! (Copy and paste it to the editor, and run the program.)
Memory rendering
This program draws a rectangle to the console, with the given size. The rectangle will be elongated, due to the characters are not perfect squares...
#####
#...#
#...#
#...#
#####
First, the program "renders" (using the save_str function), the first and last rows to the memory from address 0 to 127
(these rows are identical, so it stores it only once.) Then it renders the middle rows (with a loop) to the memory from address 128 to 255.
Finally, it renders the first full row, then the hollow ones, then the last full row. It uses 3 separate loops to accomplish it's goal.
The "size" const is for determining the side length (in characters) of the rectangle. Also, it is fun to peek in to the debug > memory tab, and watch as the values get placed there. (To actually see it, you have to slow it down.)
Challenges
- Modify the code, so it can render rectangles with sizes of 1 or 2 characters!
- Replace the size const, with a user input!
- Make it so the user can input a character, and the rectangle will be rendered with that.
#This is the size of the rectangle
# ! Keep this between 3 and 127
const size 20
#Save the "hollow" row '# #'
op R0 = 1
op R1 = size - 1
save_str 0 "#" #from addr. 0
label loopH #the "hollow loop"
save_str R0 " "
op R0 += 1
if R0 < R1 loopH
save_str R1 "#" #to addr. size-1
#Save the full row '#####'
#from addr. 128 to 128+size-1
op R0 = 0
label loopF
op R1 = R0 + 128
save_str R1 "#"
op R0 += 1
if R0 < size loopF
#Getting values
#end addr. of the full row
op R0 = size - 1
#end addr. of the hollow row
op R1 = size + 127
#num of hollow rows (-start, -end)
op R4 = size - 2
#First row
print_str 128 R1 1
#Hollow rows
op R5 = 0
label loop
print_str 0 R0 1
op R5 += 1
if R5 < R4 loop
#Last row
print_str 128 R1 1
Try it yourself! (Copy and paste it to the editor, and run the program.)
Characters and character codes
The strings in this language are stored in the memory. But, the memory can store only numbers! So, we store the characters by index. The Character code tool, can be quite helpful here.
Challenges
- Make a program that prints out all of the characters, and their indexes!
- Make a program that request an index, and prints out only the surrounding 3 characters, and their indexes
#Save "some" numbers to the memory...
save 0 72
save 1 101
save 2 108
save 3 108
save 4 111
save 5 33
#Print the numbers as characters.
print_str 0 5 1
Try it yourself! (Copy and paste it to the editor, and run the program.)
Other codes
Here are some more interesting codes.
Click on the codes to copy them. Also, for some codes the debug view can be very helpful. (For example at the Langton's ant simulation) Most of the programs below use the graphical output. If a red pixel stops at the top left of the screen, that means: Go look at the console.
#Screen filler
#width: R63
#y: R62
#color: R60
func Hline
op R61 = 0
label loopHLine
set_pixel R61 R62 R60
op R61 += 1
if R61 <= R63 loopHLine
return 0
#Covering the whole canvas in lines
op R44 = 0 #Y counter
label loop
#repeat colors after every
#4th line
op R10 = R44 % 4
op R10 += 8
op R60 = R10 #color
op R63 = 39 #width
op R62 = R44 #y
call Hline
#Animate drawing
display_color
sleep 1
#loop
op R44 += 1
if R44 <= 29 loop
#Water
op R63 = 7 #amp
op R60 = 15 #counter
label loop
clear 4
op R0 = 0 #X counter
op R1 = 0 #angle counter
label sinLoop
#get fn value
op R2 = R1 + R60
sin R2 R10
op R10 *= R63
op R10 /= 3000
op R10 += 15
#clamp values
clamp 0 39 R0 R0
clamp 0 39 R10 R10
set_pixel R0 R10 13
#fill bottom
op R5 = R10
op R5 += 1
label loopLine
set_pixel R0 R5 5
op R5 += 1
if R5 < 30 loopLine
#loop
op R0 += 1
op R1 += 12
if R0 <= 39 sinLoop
#display and animate
display_color
sleep 1
op R60 += 30
sin R60 R61
op R63 = R61
op R63 += 10
if R60 > 360 reset
jump loop
label reset
op R60 = 0
jump loop
#Cool waves
op R63 = 7 #amp
op R59 = 15 #counter
label loop
clear 0
op R0 = 0 #X counter
op R1 = 0 #angle counter
label sinLoop
#get SIN value
op R2 = R1 + R59
sin R2 R10
op R10 *= R63
op R10 /= 1000
op R10 += 15
#clamp SIN values
clamp 0 39 R0 R0
clamp 0 39 R10 R10
set_pixel R0 R10 6
#get COS value
op R2 = R1 + R59
cos R2 R10
op R10 *= R62
op R10 /= 2000
op R10 += 15
#clamp COS values
clamp 0 39 R0 R0
clamp 0 39 R10 R10
set_pixel R0 R10 7
#loop
op R0 += 1
op R1 += 12
if R0 <= 39 sinLoop
#display and animate
display_color
sleep 1
op R59 += 10
sin R59 R63
op R63 += 10
cos R59 R62
op R62 += 50
if R59 > 360 reset
jump loop
label reset
op R59 = 0
jump loop
#A platformer game
const walkingSpeed 1
const gravityFrames 2
const jumpVel 4
const tickSpeed 3 #60FPS
set_scroll 0 0
set_pixel 0 0 9
display_color
func lineNorm
set_pixel R0 1 12 #top
set_pixel R0 2 12
set_pixel R0 4 12
set_pixel R0 5 12
set_pixel R0 22 12 #bottom
set_pixel R0 23 12
set_pixel R0 25 12
set_pixel R0 26 12
set_pixel R0 28 12
set_pixel R0 29 12
set_pixel R0 43 12 #deep-bottom
set_pixel R0 44 12
set_pixel R0 46 12
set_pixel R0 47 12
return 0
func lineV1
set_pixel R0 1 1 #top
set_pixel R0 2 1
set_pixel R0 4 12
set_pixel R0 5 12
set_pixel R0 22 1 #bottom
set_pixel R0 23 1
set_pixel R0 25 12
set_pixel R0 26 12
set_pixel R0 28 1
set_pixel R0 29 1
set_pixel R0 43 12 #deep-bottom
set_pixel R0 44 12
set_pixel R0 46 1
set_pixel R0 47 1
return 0
func lineV2
set_pixel R0 1 12 #top
set_pixel R0 2 12
set_pixel R0 4 1
set_pixel R0 5 1
set_pixel R0 22 12 #bottom
set_pixel R0 23 12
set_pixel R0 25 1
set_pixel R0 26 1
set_pixel R0 28 12
set_pixel R0 29 12
set_pixel R0 43 1 #deep-bottom
set_pixel R0 44 1
set_pixel R0 46 12
set_pixel R0 47 12
return 0
func hole
set_pixel R0 21 0 #line
set_pixel R0 22 0
set_pixel R0 23 0
set_pixel R0 24 0 #line
set_pixel R0 25 0
set_pixel R0 26 0
set_pixel R0 27 0 #line
set_pixel R0 28 0
set_pixel R0 29 0
set_pixel R0 30 0 #line
return 0
func extraNorm
set_pixel R0 15 1
set_pixel R0 16 12
set_pixel R0 17 12
set_pixel R0 18 1
set_pixel R0 19 12
set_pixel R0 20 12
return 0
func extraV1
set_pixel R0 15 1
set_pixel R0 16 1
set_pixel R0 17 1
set_pixel R0 18 1
set_pixel R0 19 12
set_pixel R0 20 12
return 0
func extraV2
set_pixel R0 15 1
set_pixel R0 16 12
set_pixel R0 17 12
set_pixel R0 18 1
set_pixel R0 19 1
set_pixel R0 20 1
return 0
func resetR2
op R2 = 0
return 0
#LEVEL CREATION
op R0 = 0
op R2 = 99
label loopLevel
set_pixel R0 0 1 #top
set_pixel R0 3 1 #top
set_pixel R0 6 1 #top
set_pixel R0 21 1 #bottom
set_pixel R0 24 1 #bottom
set_pixel R0 27 1 #bottom
set_pixel R0 30 1 #bottom
set_pixel R0 42 1 #deep-bottom
set_pixel R0 45 1 #deep-bottom
set_pixel R0 48 1 #deep-bottom
op R1 = R0 % 6
if R1 != 0 lineNorm
if R1 == 3 lineV2
if R1 == 0 lineV1
if R0 == 12 resetR2
if R0 == 48 resetR2
if R0 > 60 hole
jump placeExtra
label levelLoopBack
op R0 += 1
if R0 < 80 loopLevel
jump levelEnd
label placeExtra
op R2 += 1
if R2 > 19 levelLoopBack
if R1 != 0 extraNorm
if R1 == 3 extraV2
if R1 == 0 extraV1
jump levelLoopBack
label levelEnd
#MAINLOOP
op R30 = 0 #old px
op R31 = 7 #old py
op R40 = 0 #px
op R41 = 7 #py
op R50 = 0 #pvx
op R51 = 3 #pvy
op R0 = 0
label loopGame
input_key R5
op R50 = 0
if R5 == 38 controlJump
if R5 == 37 controlLeft
if R5 == 39 controlRight
call movePlayer
call controlGrav
clamp 0 79 R40 R40 #px
clamp 7 59 R41 R41 #py
set_pixel R30 R31 0 #erase prev. player
set_pixel R40 R41 9 #draw player
op R44 = R40 - 20 #calc. scroll X
op R45 = R41 - 10 #calc. scroll Y
clamp 0 40 R44 R44
clamp 0 30 R45 R45
set_scroll R44 R45 #set scroll
display_color
op R63 = R51 * -50
clamp 0 200 R63 R63
if R63 == 0 skipSound
op R63 = 0 - R63
op R63 += 300
play_sound 1 R63 10 10
label skipSound
op R30 = R40
op R31 = R41
op R0 += 1
sleep tickSpeed
jump loopGame
#FUNCTIONS
func controlGrav
op R63 = R41 + 1
get_pixel R40 R63 R63 #pixel in front
if R63 != 0 controlGrav0
op R63 = R0 % gravityFrames
if R63 != 0 controlGravBreak
op R51 += 1 #gravity
return 0
label controlGrav0
op R51 = 0
label controlGravBreak
return 0
func movePlayer
op R62 = 0
label loopPX
sgn R50 R61
op R63 = R40 + R61
clamp 0 79 R63 R63
get_pixel R63 R41 R63 #pixel in front X
if R63 != 0 loopPXBreak
op R40 += R61
abs R50 R61
op R62 += 1
if R62 < R61 loopPX
label loopPXBreak
clamp 0 79 R40 R40 #px
op R63 = R0 % gravityFrames
if R63 != 0 loopPYBreak
op R62 = 0
label loopPY
sgn R51 R61
op R63 = R41 + R61
clamp 0 59 R63 R63
get_pixel R40 R63 R63 #pixel in front Y
if R63 != 0 loopPYBreak
op R41 += R61
abs R51 R61
op R62 += 1
if R62 < R61 loopPY
label loopPYBreak
clamp 7 59 R41 R41 #py
return 0
func controlJump
op R63 = R41 + 1
get_pixel R40 R63 R63 #pixel below player
if R63 == 0 controlJumpBreak
op R51 = 0 - jumpVel
label controlJumpBreak
return 0
func controlLeft
op R50 = 0 - walkingSpeed
return 0
func controlRight
op R50 = walkingSpeed
return 0
#Fire simulation
const numOfinstances 128
const numOfdata 2
const bgColor 0
clear bgColor
# x
# y
#
#
#Start at the middle
op R0 = 0
label loopInit
op R60 = R0 * numOfdata
op R61 = R60 + 1
save R60 20
save R61 15
op R0 += 1
if R0 < numOfinstances loopInit
#MAIN LOOP
label mainLoop
op R0 = 0
#clear 4
label renderLoop
#Load current particle data
op R60 = R0 * numOfdata
load R60 R10
op R61 = R60 + 1
load R61 R11
#R10: x
#R11: y
#Clear
set_pixel R10 R11 bgColor
rnd_range -1 1 R62
rnd_range -1 1 R63
op R10 += R62
op R11 += R63
clamp 0 39 R10 R10
clamp 0 29 R11 R11
rnd_range 8 11 R63
set_pixel R10 R11 R63
save R60 R10
save R61 R11
#Loop back
op R0 += 1
if R0 < numOfinstances renderLoop
display_color
sleep 1
jump mainLoop
#Sand simulation
const tickPerFrame 20
clear 0
#MAIN LOOP
op R30 = 0
call reset
label mainLoop
op R20 = R10
op R21 = R11
op R0 = fall
if R0 == 1 skipDraw
set_pixel R20 R21 0
set_pixel R10 R11 9
label skipDraw
op R63 = R30 % tickPerFrame
if R63 != 0 skipSleep
sleep 1
display_color
label skipSleep
#reset if landed
if R0 == 1 reset
op R30 += 1
if R30 < 17800 mainLoop
set_pixel 0 0 9
display_color
print_txt "The screen is full... :)" 1
jump 9999 #end the program
#R20: old x
#R21: old y
#R10: x
#R11: y
func reset
rnd_range 10 30 R10 #reset x
op R11 = 0 #reset y
return 0
func fall
op R63 = R11 + 1
if R63 >= 30 saveLanded #hit bottom?
clamp 0 29 R63 R63
get_pixel R10 R63 R63
if R63 != 0 tmplanded #check for X-slip
op R11 += 1 #fall if in air
return 0
label tmplanded
op R62 = R10 - 1
op R63 = R11 + 1
clamp 0 39 R62 R62
clamp 0 29 R63 R63
get_pixel R62 R63 R63 #bottom left
if R63 != 0 skipLeft
op R10 -= 1 #move left
op R11 += 1 #move down
jump skipRight
label skipLeft
op R62 = R10 + 1
op R63 = R11 + 1
clamp 0 39 R62 R62
clamp 0 29 R63 R63
get_pixel R62 R63 R63 #bottom right
if R63 != 0 skipRight
op R10 += 1 #move right
op R11 += 1 #move down
label skipRight
if R10 == R20 saveLanded #land if not moved
return 0
label saveLanded
rnd_range 10 11 R63
set_pixel R10 R11 R63
return 1
#Flappy bird
const tickSpeed 15
const gravityFrame 5
const gapHeight 8
const playerX 10
const jumpVel 1
clear 5
op R44 = -1 #score
save_str 0 " !! "
save_str 5 " ! !"
save_str 10 " ! !"
save_str 15 " ! !"
save_str 20 " !! "
save_str 25 " ! "
save_str 30 " !! "
save_str 35 " ! "
save_str 40 " ! "
save_str 45 " !!!"
save_str 50 " !! "
save_str 55 " ! !"
save_str 60 " ! "
save_str 65 " ! "
save_str 70 " !!!!"
save_str 75 " !! "
save_str 80 " ! !"
save_str 85 " ! "
save_str 90 " ! !"
save_str 95 " !! "
save_str 100 " ! ! "
save_str 105 " ! ! "
save_str 110 " !!! "
save_str 115 " ! "
save_str 120 " ! "
save_str 125 " !!!!"
save_str 130 " ! "
save_str 135 " !!! "
save_str 140 " !"
save_str 145 " !!! "
save_str 150 " !! "
save_str 155 " ! "
save_str 160 " !!! "
save_str 165 " ! !"
save_str 170 " !! "
save_str 175 " !!!"
save_str 180 " !"
save_str 185 " ! "
save_str 190 " ! "
save_str 195 " ! "
save_str 200 " !! "
save_str 205 " ! !"
save_str 210 " !! "
save_str 215 " ! !"
save_str 220 " !! "
save_str 225 " !! "
save_str 230 " ! !"
save_str 235 " !!!"
save_str 240 " !"
save_str 245 " !! "
op R5 = 0
label floorLoop
set_pixel R5 29 12
set_pixel R5 28 12
set_pixel R5 27 7
op R5 += 1
if R5 < 80 floorLoop
op R10 = playerX #X
op R11 = 10 #Y
op R20 = playerX #old X
op R21 = 10 #old Y
op R5 = 0
label mainLoop
op R60 = R5
op R60 = R60 % 40
if R60 != 0 skipPipe
op R44 += 1
op R63 = 40
call drawPipe
label skipPipe
input_key R60
call updatePlayer
call drawPlayer
op R63 = R5 % 40
set_scroll R63 0
display_color
sleep tickSpeed
op R5 += 1
jump mainLoop
func drawPlayer
set_pixel R20 R21 5
set_pixel R10 R11 11
op R20 = R10
op R21 = R11
return 0
#R10: X
#R11: Y
#R13: Yvel
#R20: old X
#R21: old Y
func updatePlayer
op R11 += R13
op R63 = R10
op R63 = R5 % 40
op R10 = R63 + playerX
op R63 = R5 % gravityFrame
if R63 != 0 skipGrav
op R13 += 1
label skipGrav
if R60 == 0 skipJump
op R13 = 0
op R13 -= jumpVel
label skipJump
if R11 >= 27 end
clamp 0 29 R11 R11
#Stop on pipe collision
get_pixel R10 R11 R63
if R63 != 5 end
return 0
#R63: pipe x
func drawPipe
op R0 = 0
label pipeLoop
set_pixel R63 R0 6
op R0 += 1
if R0 < 27 pipeLoop
rnd_range 2 10 R62
op R0 = 0
label pipeGapLoop
op R61 = R62 + R0
set_pixel R63 R61 5
op R0 += 1
if R0 <= gapHeight pipeGapLoop
return 0
label end
print_txt "SCORE: " 0
print R44 1
#10's place
op R63 = R44
op R63 -= 5
op R63 = R63 / 10
op R62 = R10 - playerX
call drawNumber
#1's place
op R63 = R44
op R63 = R63 % 10
op R62 = R10 - playerX
op R62 += 5
call drawNumber
display_color
jump 9999
#R63: the number
#R62: x coord
func drawNumber
op R60 = R63 * 20
op R0 = 0
label numloopY #R0
op R1 = 0
label numloopX #R1
op R61 = R0 * 5
op R61 += R1
op R59 = R63 * 25
op R61 += R59
load R61 R59
op R59 -= 32
if R59 != 1 skipDraw
op R59 += 1
op R58 = R1 + R62
set_pixel R58 R0 R59
label skipDraw
op R1 += 1
if R1 < 5 numloopX
op R0 += 1
if R0 < 5 numloopY
return 0
#Langton's ant
#LR configuration
#Interesting thing happens around: 10000
#(Tick counter is R0)
#Debug view is recommended...
const tickRate 100
set_scroll 20 15
op R10 = 50 #x
op R11 = 37 #y
op R12 = 1 #dir
#main loop
op R0 = 0
label mainLoop
call turnPlayer
op R63 = getInverse
set_pixel R10 R11 R63
call movePlayer
if R0 > 10000 sleep #skip skip.
op R63 = R0 % tickRate
if R63 != 0 skipSleep
label sleep
display_color
sleep 1
print R0 1
label skipSleep
op R0 += 1
jump mainLoop
func getInverse
get_pixel R10 R11 R60
if R60 == 0 white
return 0
label white
return 3
func turnPlayer
get_pixel R10 R11 R63
#ROTATE
if R63 == 0 left
if R63 == 3 right
label back
return 0
func movePlayer
#MOVE (rotated)
op R60 = R12 * 90
sin R60 R63
op R63 /= 100
cos R60 R62
op R62 /= 100
op R10 += R62
op R11 += R63
clamp 0 79 R10 R10
clamp 0 59 R11 R11
return 0
#turn left
label left
op R12 -= 1
jump back
#turn right
label right
op R12 += 1
jump back
#Rush E
const C 130
const C# 138
const D 146
const D# 155
const E 164
const F 174
const F# 185
const G 196
const G# 207
const A 220
const A# 233
const B 246
const C2 261
const D2 293
#pauses
const p1 180
const p2 360
const p4 720
const wave 1
const volume 10
op R0 = 0
label loop1
play_sound wave E p1 volume
sleep p1
op R0 += 1
if R0 <= 20 loop1
label m1
play_sound wave F p1 volume
sleep p1
play_sound wave E p1 volume
sleep p1
play_sound wave D# p1 volume
sleep p1
play_sound wave E p1 volume
sleep p2
play_sound wave A p1 volume
sleep p2
play_sound wave C2 p2 volume
sleep p2
play_sound wave C2 p1 volume
sleep p2
label m2
play_sound wave D2 p1 volume
sleep p1
play_sound wave D2 p1 volume
sleep p1
play_sound wave D2 p1 volume
sleep p1
play_sound wave D2 p1 volume
sleep p1
play_sound wave D2 p1 volume
sleep p1
play_sound wave C2 p1 volume
sleep p1
play_sound wave B p1 volume
sleep p1
play_sound wave D2 p1 volume
sleep p1
label m3
play_sound wave C2 p1 volume
sleep p1
play_sound wave C2 p1 volume
sleep p1
play_sound wave C2 p1 volume
sleep p1
play_sound wave C2 p1 volume
sleep p1
play_sound wave C2 p1 volume
sleep p1
play_sound wave B p1 volume
sleep p1
play_sound wave A p1 volume
sleep p1
play_sound wave C2 p1 volume
sleep p1
label m4
play_sound wave B p1 volume
sleep p1
play_sound wave B p1 volume
sleep p1
play_sound wave B p1 volume
sleep p1
play_sound wave B p1 volume
sleep p1
play_sound wave F# p1 volume
sleep p2
play_sound wave B p1 volume
sleep p2
play_sound wave G# p1 volume
sleep p4
play_sound wave E p2 volume
print_txt "E" 1
sleep p2
#Console "emulator"
const tickSpeed 1
const textX 12
const textY 13
const numStart 0
const bgColor 0 #background color
const fgColor 7 #text color
const brColor 6 #border color
op R44 = numStart
save_str 0 " !! "
save_str 5 " ! !"
save_str 10 " ! !"
save_str 15 " ! !"
save_str 20 " !! "
save_str 25 " ! "
save_str 30 " !! "
save_str 35 " ! "
save_str 40 " ! "
save_str 45 " !!!"
save_str 50 " !! "
save_str 55 " ! !"
save_str 60 " ! "
save_str 65 " ! "
save_str 70 " !!!!"
save_str 75 " !! "
save_str 80 " ! !"
save_str 85 " ! "
save_str 90 " ! !"
save_str 95 " !! "
save_str 100 " ! ! "
save_str 105 " ! ! "
save_str 110 " !!! "
save_str 115 " ! "
save_str 120 " ! "
save_str 125 " !!!!"
save_str 130 " ! "
save_str 135 " !!! "
save_str 140 " !"
save_str 145 " !!! "
save_str 150 " !! "
save_str 155 " ! "
save_str 160 " !!! "
save_str 165 " ! !"
save_str 170 " !! "
save_str 175 " !!!"
save_str 180 " !"
save_str 185 " ! "
save_str 190 " ! "
save_str 195 " ! "
save_str 200 " !! "
save_str 205 " ! !"
save_str 210 " !! "
save_str 215 " ! !"
save_str 220 " !! "
save_str 225 " !! "
save_str 230 " ! !"
save_str 235 " !!!"
save_str 240 " !"
save_str 245 " !! "
clear bgColor
op R0 = 0
label Hline
set_pixel R0 0 brColor #top
set_pixel R0 1 brColor
set_pixel R0 2 brColor
set_pixel R0 3 brColor
set_pixel R0 26 brColor #bottom
set_pixel R0 27 brColor
set_pixel R0 28 brColor
set_pixel R0 29 brColor
op R0 += 1
if R0 < 40 Hline
op R0 = 4
label Vline
set_pixel 0 R0 brColor #left
set_pixel 1 R0 brColor
set_pixel 2 R0 brColor
set_pixel 3 R0 brColor
set_pixel 36 R0 brColor #right
set_pixel 37 R0 brColor
set_pixel 38 R0 brColor
set_pixel 39 R0 brColor
op R0 += 1
if R0 < 26 Vline
label mainLoop
op R40 = fgColor #text color
call renderNumbers
display_color
sleep tickSpeed
op R40 = bgColor #clear color
call renderNumbers
op R44 += 1
if R44 < 128 mainLoop
op R44 = numStart
jump mainLoop
#Render the number in R44
#with color: R40
func renderNumbers
#100's place
op R63 = R44
op R63 -= 50
op R63 = R63 / 100
op R62 = textX + 0
call drawNumber
#10's place
op R63 = R44
op R63 -= 5
op R63 = R63 / 10
op R63 = R63 % 10
op R62 = textX + 5
call drawNumber
#1's place
op R63 = R44
op R63 = R63 % 10
op R62 = textX + 10
call drawNumber
return 0
#R63: the number
#R62: x coord
func drawNumber
op R60 = R63 * 20
op R0 = 0
label numloopY #R0
op R1 = 0
label numloopX #R1
op R61 = R0 * 5
op R61 += R1
op R59 = R63 * 25
op R61 += R59
load R61 R59
op R59 -= 32
if R59 != 1 skipDraw
op R59 += R40 #number's color index-1
op R59 -= 1
op R58 = R1 + R62
op R57 = R0 + textY
set_pixel R58 R57 R59
label skipDraw
op R1 += 1
if R1 < 5 numloopX
op R0 += 1
if R0 < 5 numloopY
return 0
#Snake game
#Arrow keys to move, eat the red dots.
const numOfData 2
const tickRate 30
const winLength 15 #starts from 5...
clear 0
set_scroll 0 0
#Segments saved to memory
op R44 = 5 #length
op R10 = 20 #x
op R11 = 15 #y
op R12 = 2 #Facing
op R13 = 0 #New apple needed
op R20 = R10 #old x
op R21 = R11 #old y
call savePos
set_pixel 20 10 9 #starting apple
label mainLoop
set_pixel R20 R21 6 #Snake body
set_pixel R10 R11 7 #Snake head
#Erase segment
load 0 R60
load 1 R61
get_pixel R60 R61 R63
if R63 == 9 skipErase
set_pixel R60 R61 0 #Snake clear
label skipErase
display_color
op R20 = R10
op R21 = R11
input_key R5
call inputs
call checkApple
call checkCollision
sleep tickRate
call movePlayer
call shiftMem
call savePos
if R44 < winLength mainLoop
set_pixel 0 0 7
display_color
print_txt "You win! POINTS: " 0
print R44 1
play_sound 3 262 100 10
sleep 100
play_sound 3 392 100 10
sleep 250
play_sound 3 392 500 10
sleep 500
jump 9999
label end
set_pixel 0 0 9
display_color
print_txt "You died..." 1
op R44 -= 5
print_txt "POINTS: " 0
print R44 1
play_sound 3 349 250 10
sleep 250
play_sound 3 329 250 10
sleep 250
play_sound 3 311 250 10
sleep 250
play_sound 3 293 500 10
sleep 500
jump 9999
#Functions
func inputs
if R5 == 37 inLEFT
if R5 == 38 inUP
if R5 == 39 inRIGHT
if R5 == 40 inDOWN
return 0
func inLEFT
if R12 == 1 skipLEFT
op R12 = -1
label skipLEFT
return 0
func inUP
if R12 == 0 skipUP
op R12 = 2
label skipUP
return 0
func inRIGHT
if R12 == -1 skipRIGHT
op R12 = 1
label skipRIGHT
return 0
func inDOWN
if R12 == 2 skipDOWN
op R12 = 0
label skipDOWN
return 0
func movePlayer
op R60 = R12 * 90
cos R60 R63
op R63 /= 100
sin R60 R62
op R62 /= 100
op R10 += R62
op R11 += R63
clamp 0 39 R10 R10
clamp 0 29 R11 R11
return 0
func shiftMem
op R0 = 0
label memLoop
#Current seg
op R60 = R0
op R61 = R0 + 1
op R62 = R0 + 2
op R63 = R0 + 3
#Next seg
load R62 R50
load R63 R51
#Shift
save R60 R50
save R61 R51
op R0 += numOfData
op R63 = R44 * 2
op R63 -= numOfData
if R0 < R63 memLoop
return 0
func savePos
op R60 = R44 * numOfData
op R60 -= numOfData
op R61 = R60 + 1
save R60 R10
save R61 R11
return 0
func checkCollision
op R60 = R12 * 90
cos R60 R63
op R63 /= 100
sin R60 R62
op R62 /= 100
op R50 = R10 + R62
op R51 = R11 + R63
clamp 0 39 R50 R50
clamp 0 29 R51 R51
get_pixel R50 R51 R63
if R63 == 6 end
if R63 == 7 end
return 0
func checkApple
op R60 = R12 * 90
cos R60 R63
op R63 /= 100
sin R60 R62
op R62 /= 100
op R50 = R10 + R62
op R51 = R11 + R63
clamp 0 39 R50 R50
clamp 0 29 R51 R51
get_pixel R50 R51 R63
if R63 != 9 skipEat
op R44 += 1
set_pixel R50 R51 0 #delete apple
call spawnApple
label skipEat
return 0
func spawnApple
op R13 = 0
label spawnLoop
rnd_range 4 35 R60 #5px margin 4 35
rnd_range 4 25 R61
get_pixel R60 R61 R63
if R63 != 0 spawnLoop
if checkIfOnPlayer == 1 spawnLoop
set_pixel R60 R61 9 #spawn apple
play_sound 3 200 100 10
return 0
#R60: x
#R61: y
func checkIfOnPlayer
op R62 = R60 - R10
op R63 = R61 - R11
abs R62 R62 #x distance
abs R63 R63 #y distance
#Skip if in dist: 3
if R62 <= 3 skipIf
if R61 <= 3 skipIf
return 0
label skipIf
return 1
#Fizz buzz
func fizz
print_txt "fizz" 0
return 0
func buzz
print_txt "buzz" 0
return 0
op R0 = 1
label loop
op R1 = R0 % 3
op R2 = R0 % 5
op R3 = R1 - R2
if R1 == 0 fizz
if R2 == 0 buzz
if R1 == 0 skip
if R2 == 0 skip
print R0 0
label skip
print_txt "" 1
op R0 += 1
if R0 < 20 loop