Skip to content

Mjs script syntax

Robert Jordan edited this page Apr 8, 2021 · 23 revisions

Mjs script syntax and grammar

The uncompiled .mjs script syntax looks like a fusion between C and JavaScript.

Identifiers

Prefixes and postfixes

Prefixes and postfixes are essential (and mandatory) for identifiers.

Prefix Identifiers Postfix Types
Identifies Storage
$ function -
# variable persistent
@ variable savefile
% variable thread
_ variable local
invalid -
Type
Int
% Float
$ String
# IntArray
%# FloatArray
$# StringArray

Groups

Groups act as namespaces for identifiers. A group is defined in-script with the following line:

#group "<NAME>"
Group Scope
@ local
@GLOBAL global
@<NAME> user-defined

Identifier structure

S Identifier T Group
$ handle_float % @GLOBAL

Preprocessor

#include "includes\stdio.mjh"
#group "MYNAMESPACE"
#forcecr on           // If you put this in, line breaks will be normal (force carriage return?)
#forcewipeonblank on  // The last line is \p \w automatically
#use_readflg on       // This source is judged as read (likely affects second field in .mjo script format)
#define MY_MACRO  0   // Comments can appear with defines
#if
//#elif   // usage unknown
#else
#endif

Keywords

if, else if, else
for, while, do while
switch, case, default, break, unbreak
return, goto
void, func, var
setskip, constructor, destructor

Special variables

__SYS__NumParams // number of arguments passed to function

Declarations

Variable declaration

All user-variables are required to be defined ahead of time, in similar fashion to C. Though they do not need to appear immediately at the beginning of a function, just before their usage. Variables probably do not support declarations with assignment, which includes for declarations within for loops.

var _onevar, _morevar;
var _local_var;       // value is stored in stack-frame
var %threadlocal_var; // value is stored in thread
var @savefile_var;    // value is stored in save-game
var #persistent_var;  // value is stored globally, and persists even when rebooting the game

Function declaration

Function declarations also follow similar patterns to C. The void argument seems to be mandatory when no argument's exist.

void $function_with_no_args(void) {
}
void $function_with_args(_arg1, _another_arg, _str_arg$) {
}
func $function_returns_int(void) {
}
func $function_returns_string$(void) {
}
func $function_returns_floatarray%#(void) {
}

Function predeclaration

// predeclared function contained within same script
func $check_font_change_only(void);

// predeclared functions from pic.mjo
func $picpic_shortfix$@PIC(_fn$);
void $pic_unpack_zyouzan@PIC(_to, _fn$[, _xin, _yin]);

// predeclared function from pic.mjo (within a function)
void $ame_stop@PIC();
$ame_stop@PIC(); // called immediately afterwards

Special block syntaxes

There are 3 identified types of special blocks seen in Majiro source scripts.

constructor

The constructor acts as an initialization for the function/thread(?) it's defined in. Usage of this block is not fully understood, as it's only appearance in available source scripts is immediately at the beginning of a function. If there are opcodes used specifically for the constructor, it's possible they are not required if the constructor is immediately run. This block has only ever been observed in a function also containing a destructor block, however its likely they can be used independently if there is no required cleanup.

constructor {
  //...
}

destructor

The destructor block acts as a cleanup method for the function/thread(?) it's defined in. A destructor only becomes active once execution in the function reaches the block. After which, it will be called during thread cleanup. There is potential that defining more than one destructor in a single function is supported, but any new destructor block would replace the old block, causing the old to never execute. There is one opcode dedicated to the destructor's functionality.

destructor {
  //...
}

setskip

This is a VN-related syntax. It's usage isn't fully understood, but it acts as some sort of loop and contains many type of wait executions. There are multiple opcodes used specifically for this block's functionality.

setskip {
  //...
}
Clone this wiki locally