nedoPC.org

Electronics hobbyists community established in 2002
Atom Feed | View unanswered posts | View active topics It is currently 28 Mar 2024 08:16



Reply to topic  [ 22 posts ]  Go to page 1, 2  Next
Rgrid - виртуальная машина роботов в браузере (JavaScript) 
Author Message
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
https://gitlab.com/nedopc/sdk/-/tree/master/rgrid

 history
Code:
Rgrid history
=============

v0.8 (2023-04-30)

 - Added sourcecode URL
 - Allowed $_ to control checkbox or radio as elements with value
 - Added function $append
 - Function $$_ was renamed to $$$

v0.7 (2023-04-17)

 - Added ability to send string as an argument of event
 - Fixed RECVP implementation

v0.6 (2023-04-16)

 - Fixed SEND implementation (previosly it gave JS syntax error)
 - RECV after SENDP returns 1st word of data, not size (and we ignore the rest of the packet)

v0.5 (2023-04-15)

 - Fixed implementation of COMMAND

v0.4 (2019-05-09)

 - Adaptation for updated Circuits.CC

v0.3 (2018-08-02)

 - Frameworks Webitable and Weberta were combined to single JS-file Rgrid.js

v0.2 (2012-12-24)

 - Added Weberta (RobbyVM implementation)

v0.1 (2012-12-12)

 - Initial version of Webitable


13 декабря 2012 года добавил в компилятор robbyc (бывший RW1C) возможность генерить JSON робота, например вот такой самый простой робот:
Code:
robot "Test"
author "Shaos"
main()
{
}

при компиляции превращается вот в такой JSON объект:
Code:
{"robot":"Test",
 "author":"Shaos",
 "varm":0,
 "vars":[],
 "negs":[],
 "regs":[],
 "color":"#FFFFFF",
 "code":[0,255],
 "platform":2
}

Причём в таком виде роботов можно сериализовать и передавать с узла на узел для продолжения выполнения задачи :)

P.S. Робот посложнее:
Code:
robot "Test2"
author "Shaos"
color AABBCC
main()
{
 i0 = 0;
 for(i1=0;i1<16;i1++){
 for(i2=0;i2<16;i2++){
   select i1 i2
   set i0
   i0=i0+1
 }}
}

Превратится уже вот в это:
Code:
{"robot":"Test2",
 "author":"Shaos",
 "varm":3,
 "vars":[],
 "negs":[],
 "regs":[],
 "color":"#AABBCC",
 "code":[32,1,0,0,0,0,0,32,1,1,0,0,0,0,64,12,245,14,255,245,1,0,243,245,16,0,147,244,66,1,14,255,
        0,127,0,32,1,2,0,0,0,0,64,12,245,14,255,245,2,0,243,245,16,0,147,244,66,1,14,255,0,109,0,105,
        1,1,0,1,2,0,106,1,0,0,0,0,0,64,12,245,0,0,245,0,0,243,245,1,0,160,244,64,12,245,2,0,
        245,2,0,243,245,1,0,160,244,67,0,42,0,64,12,245,1,0,245,1,0,243,245,1,0,160,244,67,0,14,0,0,
        255],
 "platform":1
}


P.P.S. Компилятор robbyc теперь сам указывает платформу. Если у робота нет оборудования, цвета и картинки, то это платформа 2 (RW1P2). Если у робота нет оборудования, но есть цвет или картинка, то это платформа 1 (RW1P1). Если у робота есть оборудование, то это платформа 0 (RW1P0 или классическая игра "Robot Warfare 1").

_________________
:dj: https://mastodon.social/@Shaos


13 Dec 2012 18:31
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Post 
Можно выдумать формат сериализуемого объекта роберты, который может содержать несколько роботов и использоваться для распределённых вычислений:

{
"rjob" : "TITLE", // наименование объекта (робото-задачи)
"author" : "NAME", // имя автора задачи
"robots" : [null,{...},{...},{...}], // массив роботов в описанном выше формате (первый элемент всегда null)
"alive" : [1,3], // причём не все из этих роботов живые - тут будет список индексов живых
"files" : {"filename1":[1,2,3],"filename2":[4,5,6]}, // это набор файлов робото-задачи
"queues" : [] // очереди обмена сообщениями в каком-то формате (пока не придумал в каком)
"lines" : [], // а это - массив линий текстового экрана, в который роботы говорят
"linem" : 25, // максимальное количество линий в предыдущем массиве
"random" : 123 // текущее состояние генератора псевдослучайных чисел
}

_________________
:dj: https://mastodon.social/@Shaos


13 Dec 2012 21:53
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Post 
Вот робот попроще:
Code:
robot "Test1"
author "Shaos"
main()
{
 b = 0
 for(a=0;a<16;a++){
  select a b
  set 255
 }
}

Он компилится вот в такой JSON:
Code:
{"robot":"Test1",
 "author":"Shaos",
 "varm":0,
 "vars":[],
 "negs":[],
 "regs":[],
 "color":"#FFFFFF",
 "code":[32,1,11,255,0,0,0,32,1,10,255,0,0,0,64,12,245,14,255,245,10,255,243,245,16,0,147,244,66,1,14,255,
        0,67,0,105,1,10,255,1,11,255,106,0,255,0,0,0,0,64,12,245,10,255,245,10,255,243,245,1,0,160,244,67,
        0,14,0,0,255],
 "platform":2
}


Листинг:
Code:
>>>>(3) main()
pcb_lib.rw1(3) START:

>>>>(4) {
>>>>(5)  b = 0
pcb_lib.rw1(5) B = 0
0000 20
0001 01
0002 0B
0003 FF
0004 00
0005 00
0006 00

>>>>(6)  for(a=0;a<16;a++){
pcb_lib.rw1(6) A=0;_l1: (A<16);IFN L _l2
0007 20
0008 01
0009 0A
000A FF
000B 00
000C 00
000D 00
000E 40
000F 0C
0010 F5
0011 0E
0012 FF
0013 F5
0014 0A
0015 FF
0016 F3
0017 F5
0018 10
0019 00
001A 93
001B F4
001C 42
001D 01
001E 0E
001F FF
0020 00
0021 43
0022 00

>>>>(7)   select a b
pcb_lib.rw1(7) SELECT A B
0023 69
0024 01
0025 0A
0026 FF
0027 01
0028 0B
0029 FF

>>>>(8)   set 255
pcb_lib.rw1(8) SET 255
002A 6A
002B 00
002C FF
002D 00
002E 00
002F 00
0030 00

>>>>(9)  }
pcb_lib.rw1(9) A=A+1;GOTO _l1;_l2:
0031 40
0032 0C
0033 F5 REG A
0034 0A
0035 FF
0036 F5 REG A
0037 0A
0038 FF
0039 F3 LOAD
003A F5 PUSH 1
003B 01
003C 00
003D A0 +
003E F4 SAVE
003F 43
0040 00
0041 0E
0042 00

>>>>(10) }
pcb_lib.rw1(10) NOP
0043 00
pcb_lib.rw1(0) __END: END
0044 FF


Как видим команды тут многобайтовые, т.е. можно написать на JS транслятор, который будет транслировать последовательности байткодов в JS-функции, которые будут запускаться браузерным JIT-компилятором JS...

_________________
:dj: https://mastodon.social/@Shaos


16 Dec 2012 18:32
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Post 
Вот так этот байткод можно оттранслировать в JS:

cat pcb_lib.txt
>>>>(3) main()
pcb_lib.rw1(3) START:

>>>>(4) {
>>>>(5) b = 0
pcb_lib.rw1(5) B = 0
0000 20 = function(r){r.regs[11]=0;r.regs[13]+=7;return r.regs[13];}
0001 01
0002 0B
0003 FF
0004 00
0005 00
0006 00

>>>>(6) for(a=0;a<16;a++){
pcb_lib.rw1(6) A=0;_l1: (A<16);IFN L _l2
0007 20 = function(r){r.regs[10]=0;r.regs[13]+=7;return r.regs[13];}
0008 01
0009 0A
000A FF
000B 00
000C 00
000D 00

000E 40 = function(r) { var lvar=[];
000F 0C
0010 F5 lvar[0] = 0xFF0E;
0011 0E
0012 FF
0013 F5 lvar[1] = 0xFF0A;
0014 0A
0015 FF
0016 F3 lvar[1] = $R.read(r,lvar[1]);
0017 F5 lvar[2] = 0x0010;
0018 10
0019 00
001A 93 lvar[1] = (lvar[1]<lvar[2])?1:0;
001B F4 $R.write(r,lvar[0],lvar[1]);
--------- r.regs[13]+=14;return r.regs[13];}

001C 42 = function(r){if(r.regs[14]==0) r.regs[13]=0x0043; else r.regs[13]+=7; return r.regs[13];}
001D 01
001E 0E
001F FF
0020 00
0021 43
0022 00

>>>>(7) select a b
pcb_lib.rw1(7) SELECT A B
0023 69 = function(r){$R.select(r.regs[10],r.regs[11]);r.regs[13]+=7;return r.regs[13];}
0024 01
0025 0A
0026 FF
0027 01
0028 0B
0029 FF

>>>>(8) set 255
pcb_lib.rw1(8) SET 255
002A 6A = function(r){$R.set(0xFF,0);r.regs[13]+=7;return r.regs[13];}
002B 00
002C FF
002D 00
002E 00
002F 00
0030 00

>>>>(9) }
pcb_lib.rw1(9) A=A+1;GOTO _l1;_l2:
0031 40 = function(r) { var lvar=[];
0032 0C
0033 F5 REG A
0034 0A
0035 FF lvar[0] = 0xFF0A;
0036 F5 REG A
0037 0A
0038 FF lvar[1] = 0xFF0A;
0039 F3 LOAD lvar[1] = $R.read(r,lvar[1]);
003A F5 PUSH 1
003B 01
003C 00 lvar[2] = 0x0001;
003D A0 + lvar[1] = lvar[1] + lvar[2];
003E F4 SAVE
--------- $R.write(r,lvar[0],lvar[1]);
--------- r.regs[13]+=14;return r.regs[13];}

003F 43 = function(r){r.regs[13]=0x000E;return r.regs[13];}
0040 00
0041 0E
0042 00

>>>>(10) }
pcb_lib.rw1(10) NOP = function(r){r.regs[13]++;return r.regs[13];}
0043 00
pcb_lib.rw1(0) __END: END

0044 FF = function(r){r.regs[15]=-1;return r.regs[13];}

P.S. Тут выходит, что одинаковые байткоды можно подменять на одну и ту же функцию (например все GOTO 0x000E будут заменены на вызов функции function(r){r.regs[13]=0x000E;return r.regs[13];} ).

P.P.S. В случае добегания до конца программы (инструкция END) мы просто говорим интерпретатору оставаться в этом же адресе (PC хранимый в r.regs[13] не меняется), а также взводим признак остановки программы - минус 1 в переменной, которая отображает глубину стека (SP хранимый в r.regs[15]).

_________________
:dj: https://mastodon.social/@Shaos


Last edited by Shaos on 17 Dec 2012 15:03, edited 5 times in total.



16 Dec 2012 19:38
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Post 
Shaos wrote:
Вот робот попроще:
Code:
robot "Test1"
author "Shaos"
main()
{
 b = 0
 for(a=0;a<16;a++){
  select a b
  set 255
 }
}

Он компилится вот в такой JSON:
Code:
{"robot":"Test1",
 "author":"Shaos",
 "varm":0,
 "vars":[],
 "negs":[],
 "regs":[],
 "color":"#FFFFFF",
 "code":[32,1,11,255,0,0,0,32,1,10,255,0,0,0,64,12,245,14,255,245,10,255,243,245,16,0,147,244,66,1,14,255,
        0,67,0,105,1,10,255,1,11,255,106,0,255,0,0,0,0,64,12,245,10,255,245,10,255,243,245,1,0,160,244,67,
        0,14,0,0,255],
 "platform":2
}



Объясняю назначение полей JSON-объекта:

robot - строка с именем робота;
author - строка с именем автора;
varm - размер области переменных, взятый из бинарника (можно пищать, если программа полезла дальше разрешённого);
vars - массив целых чисел в количестве до 32K элементов, являющийся областью переменных программы;
negs - массив целых чисел в количестве до 32K элементов, являющийся областью переменных с отрицательными индексами (будет использоваться для работы с файлами);
regs - массив целых чисел в количестве до 256 элементов, представляющий регистры робота (начало области) плюс стек (конец области);
color - цвет робота (пока не используется);
image - опциональный параметр, описывающий картинку робота 8x8 16-цветных пикселов (пока не используется);
equipment - опциональный массив оборудования робота (пока не используется);
code - массив целых чисел в количестве до 32768 элементов, являющийся областью байткода робота;
platform - тип платформы (пока работаем с платформой 2).

P.S. Все отсутствующие элементы числовых массивов будут читаться как 0.

_________________
:dj: https://mastodon.social/@Shaos


16 Dec 2012 22:11
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Post 
Shaos wrote:
Можно выдумать формат сериализуемого объекта роберты, который может содержать несколько роботов и использоваться для распределённых вычислений:

{
"rjob" : "TITLE", // наименование объекта (робото-задачи)
"author" : "NAME", // имя автора задачи
"robots" : [null,{...},{...},{...}], // массив роботов в описанном выше формате (первый элемент всегда null)
"alive" : [1,3], // причём не все из этих роботов живые - тут будет список индексов живых
"files" : {"filename1":[1,2,3],"filename2":[4,5,6]}, // это набор файлов робото-задачи
"queues" : [], // очереди обмена сообщениями в каком-то формате (пока не придумал в каком)
"lines" : [], // а это - массив линий текстового экрана, в который роботы говорят
"linem" : 25, // максимальное количество линий в предыдущем массиве
"random" : 123 // текущее состояние генератора псевдослучайных чисел
}


Придумал насчёт очередей - кроме массива сообщений queue (он будет глобальный в пределах задачи) надо ещё держать массив указателей внутри этой очереди для разных роботов, т.е.

queue: [] // массив евентов, каждый из которых тоже будет массивом в формате [i,n,x,y,k,code...]
queue_idx: [null,...] // массив индексов для роботов (указатели на элементы очереди, которые каждый робот прочитает в следующий момент вызова RECV или RECVP)

Вначале очередь евентов будет пустая, а индексы для роботов будут 0 (нулевой индекс всегда null, т.к. робота с идентификатором 0 не существует). Более детально формат каждого евента:

[I,N,X,Y,K,code...] где
I - идентификатор робота получателя (если 0, то сообщение предназначено всем);
N - идентификатор робота отправителя (если <0, то это системное сообщение - клава, мышь и т.д.);
X и Y - координаты источника события (относительные для платформы 0, игнорируются для платформы 1, абсолютные для платформы 2);
K - момент времени когда евент был отправлен (содержимое регистра T робота-отправителя);
code - посылаемый код (для получения через RECV) либо несколько кодов (для получения через RECVP).

Проблему совместимости между SEND/SENDP и RECV/RECVP можно разрешить так:
- если сообщение было послано через SEND, то по RECV получим один код, а по RECVP - пакет из одного числа (т.е. 2 числа - 1 и код);
- если сообщение было послано через SENDP и в пакете только одно число, то по RECV получим этот один код, а по RECVP - пакет из одного числа (также как и выше);
- если сообщение было послано через SENDP и в пакете больше одного числа, то по RECV будет получаться только один код (т.е. RECV придётся вызывать несколько раз, чтобы вычерпать весь пакет), а по RECVP - пакет целиком со всем содержимым.

_________________
:dj: https://mastodon.social/@Shaos


18 Dec 2012 08:54
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
В данный момент пишу JS-транслятор RW0-байткода в JS - пока вроде всё получается так, как и предполагалось :dj:

P.S. Виртуальная машина Roberta для Webitable будет называться Weberta

_________________
:dj: https://mastodon.social/@Shaos


18 Dec 2012 17:35
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Post 
Shaos wrote:
В данный момент пишу JS-транслятор RW0-байткода в JS - пока вроде всё получается так, как и предполагалось :dj:

P.S. Виртуальная машина Roberta для Webitable будет называться Weberta


Заставил работать в браузере вот такую программку:
Code:
robot "Circuits.CC v0.2"
author "Alexander Shabarshin"
+rw1_std.rwi
main()
{
 def org[17] = "LIBRARY"
 while(TRUE)
 {
  code = 0
  recv code
  if(N==0) continue
  print N
 }
}

Программка ловит клики мышки в те моменты, когда выбрана библиотеке на http://circuits.cc

Причём weberta.js уже почти 700 строк кода из себя представляет...

_________________
:dj: https://mastodon.social/@Shaos


19 Dec 2012 01:21
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Post 
Решил замерить быстродействие с помощью вот такой программульки:
Code:
obot "Circuits.CC v0.2"
author "Alexander Shabarshin"
+rw1_std.rwi
main()
{
 def org[17] = "LIBRARY"
 counter = 0
 counter2 = 0
 while(TRUE)
 {
  counter = counter+1
  if(counter==10000)
  {
    counter = 0;
    counter2 = counter2+1
  }
  code = 0
  recv code
  if(N==0) continue
  code = (X<<8)|Y
  print code
  counter = 0
  counter2 = 0
 }
}

Смотрел значение counter2 через 10 секунд после мышоклика (который сбрасывает счётчики) - они были в районе 120-130, т.е. за 10 секунд программа успевала пробежать 1200000-1300000 циклов, или в одну секунду 120000-130000 циклов (сто тысяч), что в общем-то очень неплохо :)

P.S. Один цикл как нетрудно видеть - это присвоение со сложением, сравнение, присвоение, команда получения евента, проверка на ноль, т.е. можно сказать, что 6 операций - значит в секунду моя виртуальная машина делает примерно 750000 операций...

_________________
:dj: https://mastodon.social/@Shaos


19 Dec 2012 01:47
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Post 
Для полноценного заюзывания RW0-байткода в Circuits.CC осталась самая малость - поддержать команды SELECT и SET, ну и чтение виртуальных файлов добавить...

_________________
:dj: https://mastodon.social/@Shaos


19 Dec 2012 11:02
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Post 
Shaos wrote:
Для полноценного заюзывания RW0-байткода в Circuits.CC осталась самая малость - поддержать команды SELECT и SET, ну и чтение виртуальных файлов добавить...


Поддержал - размер кода в weberta.js увеличился до 1300 строк!
Устаревших команд пока не добавлял...

P.S. Вот наиболее полный список байткодов:
Code:
 Robot Warfare 1 (Roberta)
 RW0 bytecode description
 Version 2.2

 Alexander A. Shabarshin (shaos@mail.ru)
 http://rwar.net

 November 1998 - December 2012

 Header:
 -------

0x0000: 0x00..0x02 // Version (0 for v1.*, 1 for v1.99, 2 for v2.*)
0x0001: 2 bytes // CheckSum (sum of bytes from 0x0005 to the end)
0x0003: 2 bytes // Offset to bytecode entry point (in bytes)
0x0005: 1 byte  // Length of the robot name (strlen)
0x0006: N bytes // Robot name
0x????: 0x00    // Terminal character for robot name
0x????: 2 bytes // Number of variables (plus arrays length)
0x????: 2 bytes // Code length in bytes (beginning from start point)
0x????: 3 bytes // Robot color (R,G,B)
0x????: 4 bytes // Equipments on the FRONT,RIGHT,BACK,LEFT (0-empty,1-eye,2-gun)
0x????: 1 byte  // Image flag (0x00-image is absent, 0x20-image is present)
// if image present, then next 32 bytes describe the robot image (2pix/byte)
0x????: N bytes // Author nickname
0x????: 0x00    // Terminal character for author nickname
0x????: ?? ...  // Reserved for additional data
// after that follows bytecode
START: // Entry point

 Bytecode:
 -----------------------------------------------------------------
 B - byte (1 byte)
 W - word (2 bytes - low byte + high byte)
 M - variable or constant (3-5 bytes):
     0x00 W - signed integer (-32768...+32767)
     0x01 W - variable in W cell (array[constant] is also compiled to this)
     0x02 W1 W2 - array element (W1-begin of array, W2-variables with offset)
 Registers are variables (0x01 0x?? 0xFF) with the addresses:
 0xFF00 (-256) X // register for relative X value
 0xFF01 (-255) Y // register for relative Y value
 0xFF02 (-254) D // register for distance value
 0xFF03 (-253) N // register for object value
 0xFF04 (-252) K // register for additional value
 0xFF05 (-251) R // register for random value
 0xFF06 (-250) T // register for timer value
 0xFF07 (-249) E // register for our energy value
 0xFF08 (-248) M // register for our missiles number
 0xFF09 (-247) I // register for order number of robot
 0xFF0A (-246) A // A-register for read/write
 0xFF0B (-245) B // B-register for read/write
 0xFF0C (-244) C // C-register for read/write
 0xFF0D (-243) P // register for command pointer
 0xFF0E (-242) L // register for the last value
 0xFF0F (-241) S // register for stack length
 0xFF16 (-234) U // register for higher word of timer value
 0xFF1E (-226) H // register for higher word of the last value

 labW - label with address W
 *    - old commands - supported by interpreter only
 -    - free time commands during interpretation
-----------------------------------------------------------------

 0x01 W1 W2        // DEF arr[len]  (W1-offset to array start, W2-len)
 0x02 W1 W2 W3 ... // DEF arr[len]={list}  (W3-number of words)

*0x10 W M1 M2 // IF M1<M2 : labW
*0x11 W M1 M2 // IF M1>M2 : labW
*0x12 W M1 M2 // IF M1<=M2 : labW
*0x13 W M1 M2 // IF M1>=M2 : labW
*0x14 W M1 M2 // IF M1==M2 : labW
*0x15 W M1 M2 // IF M1!=M2 : labW

-0x20 M1 M2 // M1=M2
*0x21 M1 M2 // M1=-M2
*0x22 M1 M2 M3 // M1=M2+M3
*0x23 M1 M2 M3 // M1=M2-M3
*0x24 M1 M2 M3 // M1=M2/M3
*0x25 M1 M2 M3 // M1=M2*M3
*0x26 M1 M2 M3 // M1=M2%M3
*0x27 M1 M2 M3 // M1=M2&M3 - binary AND
*0x28 M1 M2 M3 // M1=M2|M3 - binary OR
*0x29 M1 M2 M3 // M1=M2^M3 - binary XOR
*0x2A M1 M2 // M1=~M2 - binary NOT

*0x30 W // GOTO labW
*0x31 W // CALL labW
-0x33 // RET
 0x34 // STEP
 0x35 // LEFT
 0x36 // RIGHT
 0x37 ... 0x00 // SAY "string and/or &var"
 0x38 M // PRINT var
 0x3A M // ACT var (FRONT=0,RIGHT=1,BACK=2,LEFT=3)
 0x3B   // SPY
 0x3C M // RADAR var
 0x3F 0x00 B // DUMP B (Dump variables in B columns)

 0x40 B ...  // var=expr (B bytes)
-0x41 M1 M2  // IFY var1 var2
-0x42 M1 M2  // IFN var1 var2
-0x43 M      // GOTO var
-0x44 M      // CALL var

*0x51 W ... 0x00 // TEST "wildcard" label
 0x52 ... 0x00   // TEST "wildcard" // result in L register

 0x60 M // SHOT avar // copy 16 registers values to [avar]
 0x61 M1 M2 // SEND var1 var2 // send code var1 to robot var2
 0x62 M // RECV avar // receive code and save it to [avar]
-0x63   // POP // pop value from the stack and store it to register L
 0x64 M1 M2 // PIXEL varx vary // draw a pixel by foreground color
 0x65 M1 M2 // FILL vardx vardy // from last PIXEL with COLOR
 0x66 ... 00 // TEXT "string" // from last PIXEL with COLOR
 0x67 M // PLANE varn // set current plane for drawing (0 - default)
 0x68 M // COLOR varn // set current color
 0x69 M1 M2 // SELECT varx vary // select cell to draw
 0x6A M1 M2 // SET var_plane [var_side] // draw tile to selected sell (default var_side=0)
 0x6B M // GET [var_side] // get identifier of the drawn tile (default var_side=0)
 0x6C ... 00 // ASM "string" // send some string directly to the asm output (RW1P2)

 0x70 M1 M2 // COPYP avar1 avar2 // copy packet [avar2] to [avar1]
 0x71 M1 M2 // SENDP avar var // send packet [avar] to robot var
 0x72 M // RECVP avar // receive packet and save it to [avar]
 0x73   // PUSH // push value from register L to the stack
 0x74 M1 M2 // CLEAR varx vary // draw a pixel by background color
 0x7F M // COMMAND var // high-level command

 0xFF // END - end of bytecode


 Expressions
 -----------

 expr uses var,label,(,),?:,+,-,*,/,%,&,|,^,~,!,&&,||,=,==,>,<,>=,<=,!=,<<,>>

 0x80 // &&  A,B -> A&&B
 0x81 // ||  A,B -> A||B
 0x90 // ==  A,B -> A==B
 0x91 // !=  A,B -> A!=B
 0x92 // >   A,B -> A>B
 0x93 // <   A,B -> A<B
 0x94 // >=  A,B -> A>=B
 0x95 // <=  A,B -> A<=B
 0xA0 // +   A,B -> A+B
 0xA1 // -   A,B -> A-B
 0xB0 // *   A,B -> A*B
 0xB1 // /   A,B -> A/B
 0xB2 // %   A,B -> A%B
 0xC0 // &   A,B -> A&B
 0xC1 // |   A,B -> A|B
 0xC2 // ^   A,B -> A^B
 0xD0 // >>  A,B -> A>>B
 0xD1 // <<  A,B -> A<<B
 0xE0 // -   A -> -A (negative)
 0xE1 // ~   A -> ~A (bit inverse)
 0xE2 // !   A -> !A (logic NOT)
 0xF0 // ?:         A,B,C -> A?B:C
 0xF1 // DUP        A -> A,A
 0xF2 // ROL        A,B -> B,A
 0xF3 // LOAD       A -> mem[A]
 0xF4 // SAVE       A,B -> .  (mem[A]=B)
 0xF5 W // PUSH W   . -> W
 0xF6 // []         A,B -> A[B]


 Debug info
 ----------

 Debug info is added to RW0-file by option -d in RW1C v2.1 or above.
 After code compiler writes zero-terminated word "DEBUG" and list
 of source files in form zero-terminated names. Two zero bytes
 identify end of the list. Then we have list of variables:

 ? bytes - NAME,0
 2 bytes - size of variable in words
 2 bytes - index of variable

 Then we have a number of 5-bytes structures:

 1 byte - index of source file
 2 bytes - number of line in the source file
 2 bytes - address in code

 End of structures is #FF byte.


P.P.S. Байткод 0x39 затерялся где-то в анналах истории - не могу нигде найти его реализацию и даже описание...

_________________
:dj: https://mastodon.social/@Shaos


Last edited by Shaos on 20 Dec 2012 21:03, edited 1 time in total.



20 Dec 2012 16:39
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Post 
Вот такой робот на FireFox 16 (Linux) заливает весь экран 100x75 клеток за 12 секунд:
Code:
robot "Circuits.CC v0.2"
author "Alexander Shabarshin"
+rw1_std.rwi
main()
{
 def org[17] = "LIBRARY"
 while(TRUE)
 {
  code = 0
  recv code
  if(N==0) continue
  code = T
  for(A=0;A<100;A++)
  {
    for(B=0;B<75;B++)
    {
       select A B
       set 0x400
    }
  }
  code = T - code
  print code
 }
}


Причём время в этом случае считается неправильно (регистр Т который инкрементируется каждую 1/50 секунды) - видимо когда идёт взаимодействие с браузером (модификация элементов DOM веб-странички), то всё немного подтормаживает...

P.S. Замеры в разных браузерах:
Opera 12.11 (Linux) - 45 секунд
Opera 11.52 (Linux) - 57 секунд
Opera 10.63 (Linux) - 131 секунда
Opera 9.64 (Linux) - 125 секунд
Opera 12.12 (Windows) - 34 секунды
Chrome v23 (Windows) - 2 секунды
Safari v5.1.7 (Windows) - 2 секунды
FireFox 17 (Windows) - 5 секунд
Internet Explorer 8 (Windows) - 156 секунд

_________________
:dj: https://mastodon.social/@Shaos


20 Dec 2012 18:40
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Shaos wrote:
Для полноценного заюзывания RW0-байткода в Circuits.CC осталась самая малость - поддержать команды SELECT и SET, ну и чтение виртуальных файлов добавить...


Файлы читаются так - получателю -4 (@filesystem) посылается пакет с именем файла (одна буква на ячейку), далее ждём евента от @filesystem - в нём будет размер прочитанного файла, далее обращаемся (через указатели A/B/C) в отрицательную область памяти переменных (ячейки с адресами от -32K до -1) за телом файла.

Аналогичным образом можно сделать запись - добавив к имени файла какой-то суффикс, например !, что будет обозначать запись из отрицательной области памяти переменных в файл с указанным именем (длину записи можно указать следом за !)...

_________________
:dj: https://mastodon.social/@Shaos


11 Nov 2014 23:51
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Post 
Shaos wrote:
Shaos wrote:
Для полноценного заюзывания RW0-байткода в Circuits.CC осталась самая малость - поддержать команды SELECT и SET, ну и чтение виртуальных файлов добавить...


Файлы читаются так - получателю -4 (@filesystem) посылается пакет с именем файла (одна буква на ячейку), далее ждём евента от @filesystem - в нём будет размер прочитанного файла, далее обращаемся (через указатели A/B/C) в отрицательную область памяти переменных (ячейки с адресами от -32K до -1) за телом файла.

Аналогичным образом можно сделать запись - добавив к имени файла какой-то суффикс, например !, что будет обозначать запись из отрицательной области памяти переменных в файл с указанным именем (длину записи можно указать следом за !)...


Вобщем можно так сделать:
"filename" - прочитать текстовый файл в буфер (#8000...#FFFF) по одному символу в слово (т.е. 32К текстовый файл максимум);
"filename!" - записать текстовый файл из буфера начиная с #8000 и до нулевого слова (ноль при этом в файл не пишется);
"filename$" - дополнить текстовый файл строкой из буфера начиная с #8000 и до нулевого слова (ноль при этом в файл не пишется);
"filename%" - прочитать двоичный файл в буфер (#8000...#FFFF) по два байта на слово (т.е. 64К файл максимум);
"filename%S" - записать двоичный файл из буфера (#8000...#FFFF), воспользовавшись S словами.

P.S. По идее за пределы буфера #8000...#FFFF (-32768...-1) можно вылезти таким образом:
"filename!A" - записать текстовый файл строкой с адреса A до нулевого слова;
"filename$A" - дополнить текстовый файл строкой с адреса A до нулевого слова;
"filename%SA" - записать двоичный файл из адреса A воспользовавшись S словами.

P.P.S. Если хочется ещё и прочитать за пределы буфера, да ещё и со смещением, то можно сделать так:
"filename@OOSA" - прочитать из двоичного файла по смещению OO (little endian offset) S слов, начиная с адреса A (если адрес опущен, то читать начиная с #8000, а если размер опущен, то читать 32K слов).

_________________
:dj: https://mastodon.social/@Shaos


22 Nov 2014 13:21
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22409
Location: Silicon Valley
Reply with quote
Shaos wrote:
В данный момент пишу JS-транслятор RW0-байткода в JS - пока вроде всё получается так, как и предполагалось :dj:

P.S. Виртуальная машина Roberta для Webitable будет называться Weberta

Ввиду того, что я Roberta переименовал в Robby пришло время переделать и JS-интерпретатор - на днях я склеил вместе Webitable и Weberta и получил Rgrid.js :)

https://gitlab.com/nedopc/sdk/blob/master/rgrid/Rgrid.js

теперь надо Circuits.CC подправить, чтобы юзал одну новую либу вместо старых двух...

_________________
:dj: https://mastodon.social/@Shaos


03 Aug 2018 17:11
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 22 posts ]  Go to page 1, 2  Next

Who is online

Users browsing this forum: No registered users and 20 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software.