lignite 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/.rubocop.yml +12 -0
- data/NEWS.md +5 -1
- data/README.md +2 -2
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/bin/ev3tool +111 -104
- data/examples/bobbee.rb +7 -7
- data/examples/hello.rb +2 -0
- data/examples/hello.yml +4 -0
- data/examples/light-sensor.rb +2 -0
- data/examples/light-sensor.yml +3 -0
- data/examples/lights.rb +7 -7
- data/examples/lights.yml +4 -0
- data/examples/sys_list_files.rb +4 -2
- data/examples/sys_list_files.yml +9 -0
- data/lib/lignite.rb +5 -1
- data/lib/lignite/assembler.rb +6 -6
- data/lib/lignite/body_compiler.rb +4 -0
- data/lib/lignite/connection.rb +59 -1
- data/lib/lignite/connection/bluetooth.rb +7 -1
- data/lib/lignite/connection/replay.rb +57 -0
- data/lib/lignite/connection/tap.rb +45 -0
- data/lib/lignite/connection/usb.rb +10 -7
- data/lib/lignite/direct_commands.rb +56 -5
- data/lib/lignite/message.rb +8 -5
- data/lib/lignite/motors.rb +5 -5
- data/lib/lignite/op_compiler.rb +19 -18
- data/lib/lignite/rbf_object.rb +1 -1
- data/lib/lignite/system_commands.rb +30 -2
- data/lib/lignite/variables.rb +2 -2
- data/lignite.gemspec +14 -4
- data/rubocop-suse.yml +74 -0
- data/spec/connection_usb_spec.rb +42 -0
- data/spec/data/ColorReadout.rb +11 -12
- data/spec/data/HelloWorld-subop.rb +1 -1
- data/spec/data/HelloWorld.rb +1 -1
- data/spec/data/NoDebug.rb +1 -1
- data/spec/data/VernierReadout.rb +4 -4
- data/spec/direct_commands_spec.rb +25 -0
- data/spec/system_commands_spec.rb +22 -0
- metadata +28 -3
- data/lib/lignite/message_sender.rb +0 -94
data/lib/lignite/motors.rb
CHANGED
@@ -6,10 +6,10 @@ module Lignite
|
|
6
6
|
# do the DCs spawn independent threads??
|
7
7
|
# must run ready in the same block?
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
attr_reader :layer
|
10
|
+
attr_reader :nos
|
11
11
|
# @return [Lignite::DirectCommands]
|
12
|
-
|
12
|
+
attr_reader :dc
|
13
13
|
|
14
14
|
# 0x02 | 0x04 | 0x08 -> [1, 2, 3]
|
15
15
|
def nos_as_indices
|
@@ -24,7 +24,7 @@ module Lignite
|
|
24
24
|
@dc = dc
|
25
25
|
end
|
26
26
|
|
27
|
-
# TODO filter out support: official: no
|
27
|
+
# TODO: filter out support: official: no
|
28
28
|
|
29
29
|
# the type is an OUT param so the VM SETs and we GET to learn the type?
|
30
30
|
def set_type
|
@@ -62,7 +62,7 @@ module Lignite
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def start
|
65
|
-
dc.output_start(layer, nos)
|
65
|
+
dc.output_start(layer, nos) # apparently not
|
66
66
|
end
|
67
67
|
|
68
68
|
# ATTR ~polarity
|
data/lib/lignite/op_compiler.rb
CHANGED
@@ -119,7 +119,7 @@ module Lignite
|
|
119
119
|
end
|
120
120
|
|
121
121
|
enums = yml["enums"]
|
122
|
-
enums.
|
122
|
+
enums.each_value do |edata|
|
123
123
|
edata["members"].each do |mname, mdata|
|
124
124
|
load_const(mname, mdata["value"])
|
125
125
|
end
|
@@ -177,29 +177,30 @@ module Lignite
|
|
177
177
|
end
|
178
178
|
|
179
179
|
def make_lc(n, bytes = nil)
|
180
|
-
bytes ||= if (-31
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
180
|
+
bytes ||= if (-31..31).cover? n
|
181
|
+
0
|
182
|
+
elsif (-127..127).cover? n
|
183
|
+
1
|
184
|
+
elsif (-32767..32767).cover? n
|
185
|
+
2
|
186
|
+
else
|
187
|
+
4
|
188
|
+
end
|
189
189
|
make_lcn(n, bytes)
|
190
190
|
end
|
191
191
|
|
192
192
|
def make_v(n, local_or_global)
|
193
193
|
vartag = PRIMPAR_VARIABEL | local_or_global
|
194
|
-
if (0
|
195
|
-
|
196
|
-
elsif (0
|
197
|
-
|
198
|
-
elsif (0
|
199
|
-
|
194
|
+
if (0..31).cover? n
|
195
|
+
[vartag | (n & PRIMPAR_VALUE)]
|
196
|
+
elsif (0..255).cover? n
|
197
|
+
[vartag | PRIMPAR_LONG | PRIMPAR_1_BYTE, n & 0xff]
|
198
|
+
elsif (0..65535).cover? n
|
199
|
+
[vartag | PRIMPAR_LONG | PRIMPAR_2_BYTES, n & 0xff, (n >> 8) & 0xff]
|
200
|
+
else
|
201
|
+
[vartag | PRIMPAR_LONG | PRIMPAR_4_BYTES,
|
202
|
+
n & 0xff, (n >> 8) & 0xff, (n >> 16) & 0xff, (n >> 24) & 0xff]
|
200
203
|
end
|
201
|
-
[vartag | PRIMPAR_LONG | PRIMPAR_4_BYTES,
|
202
|
-
n & 0xff, (n >> 8) & 0xff, (n >> 16) & 0xff, (n >> 24) & 0xff]
|
203
204
|
end
|
204
205
|
|
205
206
|
# Reference a variable.
|
data/lib/lignite/rbf_object.rb
CHANGED
@@ -4,12 +4,24 @@ module Lignite
|
|
4
4
|
include Logger
|
5
5
|
extend Logger
|
6
6
|
|
7
|
+
def self.run(conn = Connection.create, &block)
|
8
|
+
sc = new(conn)
|
9
|
+
sc.instance_exec(&block)
|
10
|
+
sc.close
|
11
|
+
end
|
12
|
+
|
7
13
|
# @param conn [Connection]
|
8
14
|
def initialize(conn = Connection.create)
|
9
|
-
@
|
15
|
+
@conn = conn
|
10
16
|
load_yml
|
11
17
|
end
|
12
18
|
|
19
|
+
def close
|
20
|
+
@conn.close
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
13
25
|
def load_yml
|
14
26
|
fname = File.expand_path("../../../data/sysops.yml", __FILE__)
|
15
27
|
op_hash = YAML.load_file(fname)["sysops"]
|
@@ -38,7 +50,7 @@ module Lignite
|
|
38
50
|
end.join("")
|
39
51
|
logger.debug "sysop to execute: #{bytes.inspect}"
|
40
52
|
|
41
|
-
reply =
|
53
|
+
reply = system_command_with_reply(bytes)
|
42
54
|
|
43
55
|
# TODO: parse it with return_handlers
|
44
56
|
replies = return_handlers.map do |h|
|
@@ -99,5 +111,21 @@ module Lignite
|
|
99
111
|
end
|
100
112
|
end
|
101
113
|
|
114
|
+
def system_command_with_reply(instr_bytes)
|
115
|
+
cmd = Message.system_command_with_reply(instr_bytes)
|
116
|
+
@conn.send(cmd.bytes)
|
117
|
+
|
118
|
+
reply = Message.reply_from_bytes(@conn.receive)
|
119
|
+
assert_match(reply.msgid, cmd.msgid, "Reply id")
|
120
|
+
assert_match(reply.command, unpack_u8(instr_bytes[0]), "Command num")
|
121
|
+
raise VMError, format("Error: %u", reply.status) if reply.error?
|
122
|
+
|
123
|
+
reply.data
|
124
|
+
end
|
125
|
+
|
126
|
+
def assert_match(actual, expected, description)
|
127
|
+
return if actual == expected
|
128
|
+
raise "#{description} does not match, expected #{expected}, actual #{actual}"
|
129
|
+
end
|
102
130
|
end
|
103
131
|
end
|
data/lib/lignite/variables.rb
CHANGED
@@ -14,7 +14,7 @@ module Lignite
|
|
14
14
|
# declare
|
15
15
|
def add(id, size, unpacker)
|
16
16
|
raise "Duplicate variable #{id}" if @vars.key?(id)
|
17
|
-
@vars[id] = {offset: @offset, size: size}
|
17
|
+
@vars[id] = { offset: @offset, size: size }
|
18
18
|
@offset += size
|
19
19
|
@unpacker += unpacker
|
20
20
|
end
|
@@ -41,7 +41,7 @@ module Lignite
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
#
|
44
|
+
# `variables` are {Variables}
|
45
45
|
module VariableDeclarer
|
46
46
|
def data8(id)
|
47
47
|
variables.add(id, 1, "C")
|
data/lignite.gemspec
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
1
|
require File.expand_path(File.dirname(__FILE__) + "/lib/lignite/version")
|
4
2
|
|
5
3
|
Gem::Specification.new do |s|
|
@@ -20,6 +18,8 @@ TXT
|
|
20
18
|
s.files = [
|
21
19
|
".coveralls.yml",
|
22
20
|
".gitignore",
|
21
|
+
".rspec",
|
22
|
+
".rubocop.yml",
|
23
23
|
".travis.yml",
|
24
24
|
".yardopts",
|
25
25
|
"COPYING",
|
@@ -34,22 +34,27 @@ TXT
|
|
34
34
|
"data/sysops.yml",
|
35
35
|
"examples/bobbee.rb",
|
36
36
|
"examples/hello.rb",
|
37
|
+
"examples/hello.yml",
|
37
38
|
"examples/light-sensor.rb",
|
39
|
+
"examples/light-sensor.yml",
|
38
40
|
"examples/lights.rb",
|
41
|
+
"examples/lights.yml",
|
39
42
|
"examples/motors.rb",
|
40
43
|
"examples/sound.rb",
|
41
44
|
"examples/sys_list_files.rb",
|
45
|
+
"examples/sys_list_files.yml",
|
42
46
|
"lib/lignite.rb",
|
43
47
|
"lib/lignite/assembler.rb",
|
44
48
|
"lib/lignite/body_compiler.rb",
|
45
49
|
"lib/lignite/bytes.rb",
|
46
50
|
"lib/lignite/connection.rb",
|
47
51
|
"lib/lignite/connection/bluetooth.rb",
|
52
|
+
"lib/lignite/connection/replay.rb",
|
53
|
+
"lib/lignite/connection/tap.rb",
|
48
54
|
"lib/lignite/connection/usb.rb",
|
49
55
|
"lib/lignite/direct_commands.rb",
|
50
56
|
"lib/lignite/logger.rb",
|
51
57
|
"lib/lignite/message.rb",
|
52
|
-
"lib/lignite/message_sender.rb",
|
53
58
|
"lib/lignite/motors.rb",
|
54
59
|
"lib/lignite/op_compiler.rb",
|
55
60
|
"lib/lignite/rbf_object.rb",
|
@@ -57,7 +62,9 @@ TXT
|
|
57
62
|
"lib/lignite/variables.rb",
|
58
63
|
"lib/lignite/version.rb",
|
59
64
|
"lignite.gemspec",
|
65
|
+
"rubocop-suse.yml",
|
60
66
|
"spec/assembler_spec.rb",
|
67
|
+
"spec/connection_usb_spec.rb",
|
61
68
|
"spec/data/ColorReadout.lms",
|
62
69
|
"spec/data/ColorReadout.rb",
|
63
70
|
"spec/data/ColorReadout.rbf",
|
@@ -72,13 +79,16 @@ TXT
|
|
72
79
|
"spec/data/VernierReadout.lms",
|
73
80
|
"spec/data/VernierReadout.rb",
|
74
81
|
"spec/data/VernierReadout.rbf",
|
75
|
-
"spec/
|
82
|
+
"spec/direct_commands_spec.rb",
|
83
|
+
"spec/spec_helper.rb",
|
84
|
+
"spec/system_commands_spec.rb"
|
76
85
|
]
|
77
86
|
|
78
87
|
s.executables = s.files.grep(/^bin\//) { |f| File.basename(f) }
|
79
88
|
|
80
89
|
s.required_ruby_version = ">= 2.1" # mandatory keyword arguments
|
81
90
|
s.add_dependency "libusb", "~> 0.6"
|
91
|
+
s.add_dependency "thor", "~> 0.19"
|
82
92
|
|
83
93
|
s.add_development_dependency "coveralls", "~> 0"
|
84
94
|
s.add_development_dependency "simplecov", "~> 0"
|
data/rubocop-suse.yml
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# This is the shared Rubocop configuration for SUSE projects. It is maintained
|
2
|
+
# at https://github.com/SUSE/style-guides/blob/master/rubocop-suse.yml
|
3
|
+
#
|
4
|
+
# The configuration is tested and used with the Rubocop version used by Hound
|
5
|
+
# (https://houndci.com).
|
6
|
+
#
|
7
|
+
# We use the default Hound config as a baseline:
|
8
|
+
#
|
9
|
+
# https://raw.githubusercontent.com/thoughtbot/hound/master/config/style_guides/ruby.yml
|
10
|
+
#
|
11
|
+
# This file contains the rules with derive from this.
|
12
|
+
|
13
|
+
Lint/EndAlignment:
|
14
|
+
StyleGuide: https://github.com/SUSE/style-guides/blob/master/Ruby.md#lintendalignment
|
15
|
+
EnforcedStyleAlignWith: variable
|
16
|
+
|
17
|
+
Metrics/AbcSize:
|
18
|
+
StyleGuide: https://github.com/SUSE/style-guides/blob/master/Ruby.md#metricsabcsize
|
19
|
+
Max: 30
|
20
|
+
|
21
|
+
Metrics/LineLength:
|
22
|
+
StyleGuide: https://github.com/SUSE/style-guides/blob/master/Ruby.md#metricslinelength
|
23
|
+
Max: 100
|
24
|
+
# To make it possible to copy or click on URIs in the code, we allow lines
|
25
|
+
# contaning a URI to be longer than Max.
|
26
|
+
AllowURI: true
|
27
|
+
URISchemes:
|
28
|
+
- http
|
29
|
+
- https
|
30
|
+
|
31
|
+
Style/AlignHash:
|
32
|
+
StyleGuide: https://github.com/SUSE/style-guides/blob/master/Ruby.md#stylealignhash
|
33
|
+
EnforcedHashRocketStyle: table
|
34
|
+
EnforcedColonStyle: table
|
35
|
+
|
36
|
+
Style/AlignParameters:
|
37
|
+
StyleGuide: https://github.com/SUSE/style-guides/blob/master/Ruby.md#stylealignparameters
|
38
|
+
Enabled: false
|
39
|
+
|
40
|
+
Style/CollectionMethods:
|
41
|
+
StyleGuide: https://github.com/SUSE/style-guides/blob/master/Ruby.md#stylecollectionmethods
|
42
|
+
Enabled: false
|
43
|
+
|
44
|
+
Style/EmptyLinesAroundBlockBody:
|
45
|
+
StyleGuide: https://github.com/SUSE/style-guides/blob/master/Ruby.md#styleemptylinesaroundblockbody
|
46
|
+
Enabled: false
|
47
|
+
|
48
|
+
Style/MultilineOperationIndentation:
|
49
|
+
StyleGuide: https://github.com/SUSE/style-guides/blob/master/Ruby.md#stylemultilineoperationindentation
|
50
|
+
EnforcedStyle: indented
|
51
|
+
|
52
|
+
Style/StringLiterals:
|
53
|
+
StyleGuide: https://github.com/SUSE/style-guides/blob/master/Ruby.md#stylestringliterals
|
54
|
+
EnforcedStyle: double_quotes
|
55
|
+
|
56
|
+
Style/StringLiteralsInInterpolation:
|
57
|
+
StyleGuide: https://github.com/SUSE/style-guides/blob/master/Ruby.md#stylestringliteralsininterpolation
|
58
|
+
EnforcedStyle: double_quotes
|
59
|
+
|
60
|
+
Style/WordArray:
|
61
|
+
StyleGuide: https://github.com/SUSE/style-guides/blob/master/Ruby.md#deviations-from-the-upstream-style-guide
|
62
|
+
Enabled: false
|
63
|
+
|
64
|
+
Style/RegexpLiteral:
|
65
|
+
StyleGuide: https://github.com/SUSE/style-guides/blob/master/Ruby.md#deviations-from-the-upstream-style-guide
|
66
|
+
Enabled: false
|
67
|
+
|
68
|
+
Style/SignalException:
|
69
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#fail-method
|
70
|
+
EnforcedStyle: only_raise
|
71
|
+
|
72
|
+
Style/NumericLiterals:
|
73
|
+
StyleGuide: https://github.com/SUSE/style-guides/blob/master/Ruby.md#stylenumericliterals
|
74
|
+
Enabled: false
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
require "lignite"
|
3
|
+
|
4
|
+
describe Lignite::Connection::Usb do
|
5
|
+
let(:device) do
|
6
|
+
instance_double("FakeDevice", interfaces: [interface])
|
7
|
+
end
|
8
|
+
let(:interface) { double("FakeInterface", endpoints: [in_ep, out_ep]) }
|
9
|
+
let(:in_ep) { double("InEndpoint", direction: :in) }
|
10
|
+
let(:out_ep) { double("OutEndpoint", direction: :out) }
|
11
|
+
let(:dev_handle) { double("FakeDevHandle") }
|
12
|
+
|
13
|
+
before(:each) do
|
14
|
+
usb = instance_double("FakeContext", devices: [device])
|
15
|
+
allow(LIBUSB::Context).to receive(:new).and_return(usb)
|
16
|
+
allow(dev_handle).to receive(:"auto_detach_kernel_driver=")
|
17
|
+
allow(dev_handle).to receive(:claim_interface).and_yield
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#write" do
|
21
|
+
it "does not crash" do
|
22
|
+
data = "hello"
|
23
|
+
allow(device).to receive(:open).and_yield(dev_handle)
|
24
|
+
allow(dev_handle).to receive(:interrupt_transfer).and_return(data.bytesize)
|
25
|
+
expect { subject.write(data) }.to_not raise_error
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#read" do
|
30
|
+
it "does not crash" do
|
31
|
+
allow(device).to receive(:open).and_yield(dev_handle)
|
32
|
+
allow(dev_handle).to receive(:interrupt_transfer).and_return("hello")
|
33
|
+
expect(subject.read(1000)).to eq("hello")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#write" do
|
38
|
+
it "does not crash" do
|
39
|
+
expect { subject.close }.to_not raise_error
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/spec/data/ColorReadout.rb
CHANGED
@@ -15,38 +15,37 @@ vmthread :MAIN do
|
|
15
15
|
data8 :Mode
|
16
16
|
data8 :State
|
17
17
|
|
18
|
-
|
19
18
|
move8_8(3, :Mode)
|
20
19
|
|
21
|
-
|
20
|
+
loop do
|
22
21
|
ui_draw(FILLWINDOW, 0x00, 0, 0)
|
23
22
|
ui_draw(SELECT_FONT, SMALL_FONT)
|
24
|
-
ui_draw(TEXT, FG_COLOR, 0, 10,
|
25
|
-
ui_draw(TEXT, FG_COLOR, 0, 30,
|
23
|
+
ui_draw(TEXT, FG_COLOR, 0, 10, " Color Readout V0.00 ")
|
24
|
+
ui_draw(TEXT, FG_COLOR, 0, 30, "Mode ")
|
26
25
|
|
27
|
-
ui_draw(TEXT, FG_COLOR, 0, 50,
|
28
|
-
ui_draw(TEXT, FG_COLOR, 0, 65,
|
29
|
-
ui_draw(TEXT, FG_COLOR, 0, 80,
|
30
|
-
ui_draw(TEXT, FG_COLOR, 0, 118,
|
26
|
+
ui_draw(TEXT, FG_COLOR, 0, 50, "Raw 1")
|
27
|
+
ui_draw(TEXT, FG_COLOR, 0, 65, "Raw 2")
|
28
|
+
ui_draw(TEXT, FG_COLOR, 0, 80, "Raw 3")
|
29
|
+
ui_draw(TEXT, FG_COLOR, 0, 118, "Left = 3 Right = 4")
|
31
30
|
ui_draw(SELECT_FONT, NORMAL_FONT)
|
32
31
|
|
33
32
|
move8_32(:Mode, :Data1)
|
34
33
|
and32(:Data1, 0xFF, :Data1)
|
35
|
-
strings(NUMBER_FORMATTED, :Data1,
|
34
|
+
strings(NUMBER_FORMATTED, :Data1, "%1d", 8, :String)
|
36
35
|
ui_draw(TEXT, FG_COLOR, 64, 30, :String)
|
37
36
|
|
38
37
|
input_device(READY_RAW, 0, PORT, 0, :Mode, 3, :Data1, :Data2, :Data3)
|
39
38
|
|
40
39
|
and32(:Data1, 0xFFFF, :Data1)
|
41
|
-
strings(NUMBER_FORMATTED, :Data1,
|
40
|
+
strings(NUMBER_FORMATTED, :Data1, "%-5d", 8, :String)
|
42
41
|
ui_draw(TEXT, FG_COLOR, 64, 50, :String)
|
43
42
|
|
44
43
|
and32(:Data2, 0xFFFF, :Data2)
|
45
|
-
strings(NUMBER_FORMATTED, :Data2,
|
44
|
+
strings(NUMBER_FORMATTED, :Data2, "%-5d", 8, :String)
|
46
45
|
ui_draw(TEXT, FG_COLOR, 64, 65, :String)
|
47
46
|
|
48
47
|
and32(:Data3, 0xFFFF, :Data3)
|
49
|
-
strings(NUMBER_FORMATTED, :Data3,
|
48
|
+
strings(NUMBER_FORMATTED, :Data3, "%-5d", 8, :String)
|
50
49
|
ui_draw(TEXT, FG_COLOR, 64, 80, :String)
|
51
50
|
|
52
51
|
ui_draw(UPDATE)
|
data/spec/data/HelloWorld.rb
CHANGED
data/spec/data/NoDebug.rb
CHANGED
data/spec/data/VernierReadout.rb
CHANGED
@@ -5,18 +5,18 @@ vmthread :MAIN do
|
|
5
5
|
data32 :Data1
|
6
6
|
datas :String, 8
|
7
7
|
|
8
|
-
|
8
|
+
loop do
|
9
9
|
ui_draw(FILLWINDOW, 0x00, 0, 0)
|
10
10
|
ui_draw(SELECT_FONT, SMALL_FONT)
|
11
|
-
ui_draw(TEXT, FG_COLOR, 0, 10,
|
11
|
+
ui_draw(TEXT, FG_COLOR, 0, 10, "Vernier Readout V0.00")
|
12
12
|
|
13
|
-
ui_draw(TEXT, FG_COLOR, 0, 50,
|
13
|
+
ui_draw(TEXT, FG_COLOR, 0, 50, "Raw 1")
|
14
14
|
ui_draw(SELECT_FONT, NORMAL_FONT)
|
15
15
|
|
16
16
|
input_device(READY_RAW, 0, PORT, 1, 0, 1, :Data1)
|
17
17
|
|
18
18
|
and32(:Data1, 0xFFFF, :Data1)
|
19
|
-
strings(NUMBER_FORMATTED, :Data1,
|
19
|
+
strings(NUMBER_FORMATTED, :Data1, "%-5d", 8, :String)
|
20
20
|
ui_draw(TEXT, FG_COLOR, 64, 50, :String)
|
21
21
|
|
22
22
|
ui_draw(UPDATE)
|