Skip to content

Latest commit

 

History

History
266 lines (193 loc) · 8.03 KB

README.md

File metadata and controls

266 lines (193 loc) · 8.03 KB

tiQ Logo

tiQ

Tiny 16bit fantasy console written in TypeScript


A simple virtual console I made for training purposes. The project consists of a 16bit virtual machine, compiler, decompiler, CLI and web GUI.

Table of Contents


Specifications

  • Display: 32x32 Black & White
  • Input: 6 buttons
  • Supports 16 Instructions
  • Memory: 8kb (Can store up to 4096 instructions)

Web GUI

The /web folder contains the web gui, through which you can run executable files. Also, GUI available here:

The console screen is rendered on Canvas element and the VM logs are printed in the DevTools console. Also, you can interact with the VM by stopping it, executing one step, or starting it up again.


CLI

This repository contains a CLI that you can use to compile source code and decompile binary files. Since CLI is written in TypeScript, you need to compile it first, or use ts-node utility.

For more information, type:

ts-node ./source/cli.ts help

Examples:

ts-node ./source/cli.ts compile source.tiq executable.bin
ts-node ./source/cli.ts decompile executable.bin source.tiq

Instruction Set

Each instruction consists of 16 bits. 4 bits used to store opcode ( type of instruction ), and other 12 bits to store arguments.

  • Algorithm used for building instructions: (4096 * opcode) + argument
  • Algorithm for draw instruction: (4096 * 15) + (128 * x) + (4 * y) + (1 * color)

0. NOTHING

Store number from 0 to 4095.

1. LOAD, address

Load the number from the specified address into the accumulator.

2. SAVE, address

Save accumulator value to specified memory address.

3. ADD, address

Add a number from the specified address to the accumulator.

4. SUBSTRACT, address

Subtract from the accumulator the number from the specified address.

5. EQUAL, address

Set accumulator value to 1 if the current accumulator value is the same as the value in the specified address. Otherwise, accumulator value will be set to 0.

6. LESS, address

Set accumulator value to 1 if the current accumulator value less than value in the specified address. Otherwise, accumulator value will be set to 0.

7. GREATER, address

Set accumulator value to 1 if the current accumulator value greater than value in the specified address. Otherwise, accumulator value will be set to 0.

8. AND, address

Set accumulator value to 1 if the current accumulator and address values are positive (greater than 0). Otherwise, accumulator value will be set to 0.

9. OR, address

Set accumulator value to 1 if the current accumulator and address values equals to 0. Otherwise, accumulator value will be set to 0.

10. JUMP, address

Set the counter (current execution address), to the specified address. The specified address will be executed on the next tick.

11. TRUE, address

If accumulator value is positive, set the counter to the specified address. The specified address will be executed on the next tick.

12. FALSE, address

If accumulator value equals to 0, set the counter to the specified address. The specified address will be executed on the next tick.

13. RANDOM, maximum

Set the accumuator to random number between 0 and the specified maximum.

14. INPUT, key

Set the accumulator to 1 if the specified button is pressed. If not pressed, the accumulator will be set to 0.

15. DISPLAY, x, y, color

Change pixel color on specified coordinates. X and Y arguments must be between 0 and 31. Color argument must be 1 or 0.


Assembly Syntax

The best way to write tiQ programs is to use the tiQ Assembler, which can be translated into vm instructions using a compiler.

Source code files must have the extension .tiq. For executable files it is best to use the .bin extension.

comments

Compiler supports single line comments. Any text between // and the end of the line will be ignored.

begin & end

Every tiQ program begins and ends with these key words. Anything not in between will be ignored.

Example:

Just information, will not be processed

begin
	// Your code goes here
end

finish

Indicates the end of program execution. During compilation this keyword will translate to 0. The result is the same as from nothing, 0 or just 0.

raw

The compiler supports raw instructions. You can specify an instruction as a number between 0 and 65535.

Example:

begin
	0 // Same as finish keyword
	4098 // Same as load, 2 (Since 4096 * 1 + 2 will be 4098)
end

declare, address, value

You can declare a raw instruction or number at a specified address using the keyword declare. All declarations must be at the beginning of the program, since they will be processed only at compilation time.

Example:

begin
	declare, 500, 1000 // Declare number 1000 on address 500
end

:label

You can specify the label using the format :string. To jump to label address, use the label as an argument instead of the address.

Example:

begin
	jump, :here 
	finish // Will not be executed

	:here
	// Your code
end

nothing, number

You can declare a number using this keyword. The number must be between 0 and 4095.

Example:

begin
	nothing, 100 // Declare number 100
end

load, address

Load the number from the specified address into the accumulator.

Example:

begin
	declare, 1000, 99
	load, 1000 // Load value from address 1000 (Accumulator will be 99)
end

save, address

Save accumulator value to specified address.

add, address

Add a number from the specified address to the accumulator.

substract, address

Subtract from the accumulator the number from the specified address.

equal, address

Set accumulator value to 1 if the current accumulator value is the same as the value in the specified address. Otherwise, accumulator value will be set to 0.

less, address

Set accumulator value to 1 if the current accumulator value less than value in the specified address. Otherwise, accumulator value will be set to 0.

greater, address

Set accumulator value to 1 if the current accumulator value greater than value in the specified add

and, address

Set accumulator value to 1 if the current accumulator and address values are positive (greater than 0). Otherwise, accumulator value will be set to 0.

or, address

Set accumulator value to 1 if the current accumulator and address values equals to 0. Otherwise, accumulator value will be set to 0.

jump, address / label

Set the counter (current execution address), to the specified address or label. The specified address will be executed on the next tick.

Example:

begin
	:start
	jump, :here
	nothing, 0 // Never will be executed

	:here
	jump, 0 // Jump to start label, because 0 is the beginning of the code.
end

true, address / label

Same as jump, but will be executed only when current accumulator value is positive (greater than 0).

false, address / label

Same as jump, but will be executed only when current accumulator value equals to 0.

random, maximum

Set the accumuator to random number between 0 and the specified maximum. Maximal possible value is 4095.

input, key

Set the accumulator to 1 if the specified button is pressed. If not pressed, the accumulator will be set to 0.

Possible keys:

  • 0 - arrow up.
  • 1 - arrow down.
  • 2 - arrow left.
  • 3 - arrow right.
  • 4 - key Z.
  • 5 - key X.

display, x, y, color

Change pixel color on specified coordinates. X and Y arguments must be between 0 and 31. Color argument must be 1 or 0.

Example:

begin
	display, 0, 0, 1 // Set top left pixel to black
	display, 31, 31, 1 // Set bottom right pixel to black
end