burn 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/README.md +56 -569
  2. data/lib/burn.rb +5 -3
  3. data/lib/burn/cli.rb +160 -199
  4. data/lib/burn/config.rb +4 -0
  5. data/lib/burn/config/app.rb +15 -0
  6. data/lib/burn/config/config_base.rb +16 -0
  7. data/lib/burn/config/loader.rb +23 -0
  8. data/lib/burn/config/server.rb +11 -0
  9. data/lib/burn/fuel.rb +11 -0
  10. data/lib/burn/{dsl → fuel}/dsl_base.rb +1 -1
  11. data/lib/burn/fuel/rom/channel_stream.rb +106 -0
  12. data/lib/burn/fuel/rom/declare.rb +43 -0
  13. data/lib/burn/fuel/rom/music.rb +37 -0
  14. data/lib/burn/fuel/rom/note.rb +126 -0
  15. data/lib/burn/fuel/rom/scene.rb +279 -0
  16. data/lib/burn/fuel/rom/sound.rb +31 -0
  17. data/lib/burn/fuel/rom/sound_effect.rb +92 -0
  18. data/lib/burn/fuel/telnet/declare.rb +26 -0
  19. data/lib/burn/fuel/telnet/scene.rb +112 -0
  20. data/lib/burn/generator.rb +10 -3
  21. data/lib/burn/generator/rom/assembly_music.rb +49 -0
  22. data/lib/burn/generator/rom/assembly_sound_effect.rb +35 -0
  23. data/lib/burn/generator/rom/c_source.rb +55 -0
  24. data/lib/burn/generator/{template → rom/template}/mus_template.s +0 -0
  25. data/lib/burn/generator/{template → rom/template}/template.c +0 -0
  26. data/lib/burn/generator/rom_builder.rb +67 -0
  27. data/lib/burn/generator/telnet/jit_compiler.rb +41 -0
  28. data/lib/burn/generator/telnet/screen.rb +86 -0
  29. data/lib/burn/generator/telnet/sprite.rb +16 -0
  30. data/lib/burn/generator/telnet/user_input.rb +25 -0
  31. data/lib/burn/generator/telnet_vm.rb +50 -0
  32. data/lib/burn/pxes.rb +3 -0
  33. data/lib/burn/{util/pxes.rb → pxes/cc65_transpiler.rb} +8 -14
  34. data/lib/burn/pxes/cruby_transpiler.rb +189 -0
  35. data/lib/burn/pxes/transpiler_base.rb +14 -0
  36. data/lib/burn/server.rb +2 -0
  37. data/lib/burn/server/rom.rb +24 -0
  38. data/lib/burn/server/telnet.rb +120 -0
  39. data/lib/burn/util.rb +1 -2
  40. data/lib/burn/util/logo.rb +68 -0
  41. data/lib/burn/util/os.rb +1 -1
  42. data/lib/burn/version.rb +1 -1
  43. metadata +53 -19
  44. data/lib/burn/builder.rb +0 -65
  45. data/lib/burn/dsl.rb +0 -8
  46. data/lib/burn/dsl/channel_stream.rb +0 -105
  47. data/lib/burn/dsl/declare.rb +0 -42
  48. data/lib/burn/dsl/music.rb +0 -36
  49. data/lib/burn/dsl/note.rb +0 -125
  50. data/lib/burn/dsl/scene.rb +0 -278
  51. data/lib/burn/dsl/sound.rb +0 -30
  52. data/lib/burn/dsl/sound_effect.rb +0 -91
  53. data/lib/burn/generator/assembly_music.rb +0 -47
  54. data/lib/burn/generator/assembly_sound_effect.rb +0 -33
  55. data/lib/burn/generator/c_source.rb +0 -54
  56. data/lib/burn/util/server.rb +0 -21
@@ -1,105 +0,0 @@
1
- module Burn
2
- module Dsl
3
- class ChannelStream
4
- # tempo 193 ~ 211 (18 levels, 202 is median)
5
- # see: http://ja.wikipedia.org/wiki/%E6%BC%94%E5%A5%8F%E8%A8%98%E5%8F%B7
6
- TEMPO_BASE = 192
7
- PRESTO = 1 + TEMPO_BASE
8
- ALLEGRO = 2 + TEMPO_BASE
9
- MODERATO = 3 + TEMPO_BASE
10
- ANDANTE = 4 + TEMPO_BASE
11
- ADAGIO = 5 + TEMPO_BASE
12
- LARGO = 6 + TEMPO_BASE
13
-
14
- # instrument number 64~126 (62steps) *note* no sound for 64, 65~72 seems working right now
15
- BASS = 65
16
- PIANO = 66
17
- STRING = 67
18
- ARPEGGIO = 68
19
- STEP = 69
20
- BELL = 70
21
- ACOUSTIC = 71
22
- GUITAR = 72
23
- THEREMIN = 73
24
-
25
- def initialize(index, instrument, tempo)
26
- @index = index
27
-
28
- @duration_list = [:half, :quarter, :eighth, :sixteenth]
29
- @duration_numeric_list = {2=>:half, 4=>:quarter, 8=>:eighth, 16=>:sixteenth}
30
- @duration_symbol_list = [:dotted, :triplet]
31
- @articulation_list = [:tenuto, :staccato, :accent]
32
- @instrument_list = [:piano, :bass]
33
-
34
- @notes = Array.new
35
- @notes << ChannelStream.const_get(tempo.upcase)
36
- @notes << ChannelStream.const_get(instrument.upcase)
37
-
38
- @default_duration = :quarter
39
- @default_articulation = nil
40
- @default_pitch = :c0
41
-
42
- @output_buffer = Array.new
43
- end
44
-
45
- def default(*args)
46
- args.each{ |option|
47
- if @duration_numeric_list.include?(option) then
48
- @default_duration = @duration_numeric_list[option]
49
- elsif @duration_list.include?(option) then
50
- @default_duration = option
51
- elsif @articulation_list.include?(option) then
52
- @default_articulation = option
53
- end
54
- }
55
- end
56
-
57
- def method_missing(method_symbol, *args, &block)
58
- case method_symbol
59
- when :segno then
60
- @output_buffer << __translate
61
- @output_buffer << "@chn#{@index.to_s}_segno:"
62
- @notes = Array.new
63
- when :dal_segno then
64
- @output_buffer << __translate
65
- @output_buffer << " .byte $fe" # end of stream
66
- @output_buffer << " .word @chn#{@index.to_s}_segno"
67
- @notes = Array.new
68
- else
69
- note = Note.new(@default_duration, method_symbol, @default_articulation)
70
- args.each{ |option|
71
- if @duration_numeric_list.include?(option) then
72
- note.duration = @duration_numeric_list[option]
73
- elsif @duration_list.include?(option) then
74
- note.duration = option
75
- elsif @articulation_list.include?(option) then
76
- note.articulation = option
77
- elsif @duration_symbol_list.include?(option) then
78
- note.duration_symbol = option
79
- end
80
- }
81
- @notes.concat note.generate
82
- end
83
- end
84
-
85
- def load(&block)
86
- self.instance_eval &block
87
- end
88
-
89
- def generate
90
- if @notes.count>0 then
91
- @output_buffer << __translate
92
- end
93
- @output_buffer.join("\n")
94
- # " .byte " + @notes.map{|p| "$%02x" % p}.join(",")
95
- # " .byte $c1,$43,$1d,$80,$1f,$80,$21,$82,$1d,$80,$1d,$80,$1f,$92"
96
- end
97
-
98
- private
99
- def __translate
100
- " .byte " + @notes.map{|p| "$%02x" % p}.join(",")
101
- end
102
-
103
- end
104
- end
105
- end
@@ -1,42 +0,0 @@
1
- module Burn
2
- module Dsl
3
- class Declare < DslBase
4
-
5
- def initialize(resource_name, context)
6
- super(resource_name, context)
7
- end
8
-
9
- def method_missing(method_symbol, *args, &block)
10
- log :method_symbol=>method_symbol, :args=>args, block=>block
11
-
12
- proc = Proc.new{|args|
13
- key=args.shift
14
- value=args.shift
15
- if value.is_a?(String) then
16
- patternizer = Burn::Util::Patternizer.new(value)
17
-
18
- struct_var = "static sprite_schema #{key}={0, 0, {"
19
- @pattern_table_index[key.to_sym] = @pattern_table_pointer
20
- patternizer.patterns.each_with_index do |p, i|
21
- log p, i, patternizer.height, "aaaaaaaaaaaaaaaaaaa"
22
- struct_var += sprintf("%d, %d, %#x, 0,", (i % patternizer.width)*8 , (i / (patternizer.patterns.size / patternizer.height) )*8 , @pattern_table_pointer)
23
- @pattern_tables << p
24
- @pattern_table_pointer+=1
25
- end
26
- struct_var += "128}};"
27
-
28
- @global.push sprintf(struct_var, "")
29
-
30
- else
31
- @global.push "static unsigned char #{key};"
32
- @code_blocks.push "#{key}="+sprintf("%#x", value)+";"
33
- log :key=>key, :value=>value.to_s(16), :value_class=>value.class
34
- end
35
- }
36
-
37
- @context.instance_exec [method_symbol.to_s, args[0]], &proc
38
- end
39
-
40
- end
41
- end
42
- end
@@ -1,36 +0,0 @@
1
- module Burn
2
- module Dsl
3
- class Music < DslBase
4
- def initialize(resource_name, context)
5
- super(resource_name, context)
6
-
7
- @default_tempo = :allegro
8
-
9
- if resource_name.nil? then
10
- raise Exception.new "Resource name for Music class must be provided."
11
- else
12
- @resource_name = resource_name
13
- end
14
-
15
- @context.instance_exec resource_name, &lambda{|resource_name|
16
- @resources["#{resource_name}"] = Array.new
17
- }
18
-
19
- end
20
-
21
- def channel(instrument, &block)
22
- @context.instance_exec(@resource_name,@default_tempo) do |resource_name, default_tempo|
23
- stream = ChannelStream.new(@resources["#{resource_name}"].count, instrument, default_tempo)
24
- stream.load(&block)
25
- @resources["#{resource_name}"] << stream.generate
26
- #@resources["#{resource_name}"] << " .byte $43,$1d,$80,$1f,$80,$21,$82,$1d,$80,$1d,$80,$1f,$92"
27
- end
28
- end
29
-
30
- def tempo(speed)
31
- @default_tempo = speed
32
- end
33
-
34
- end
35
- end
36
- end
data/lib/burn/dsl/note.rb DELETED
@@ -1,125 +0,0 @@
1
- module Burn
2
- module Dsl
3
- class Note
4
- # For music
5
- # (0..59 are octaves 1-5, 63 note stop)
6
- C = 0
7
- D = 2
8
- E = 4
9
- F = 5
10
- G = 7
11
- A = 9
12
- B = 11
13
-
14
- CS = 11
15
- DS = 1
16
- ES = 3
17
- FS = 4
18
- GS = 6
19
- AS = 8
20
- BS = 10
21
-
22
- REST = -1
23
-
24
-
25
- # Empty Rows 128~191 (63steps)
26
- DURATION_BASE = 127
27
- SIXTEENTH = 4 + DURATION_BASE
28
- EIGHTH = 10 + DURATION_BASE
29
- QUARTER = 22 + DURATION_BASE
30
- HALF = 46 + DURATION_BASE
31
- DOTTED_SIXTEENTH = 7 + DURATION_BASE
32
- DOTTED_EIGHTH = 16 + DURATION_BASE
33
- DOTTED_QUARTER = 34 + DURATION_BASE
34
- DOTTED_HALF = 70 + DURATION_BASE
35
- TRIPLET_SIXTEENTH = 1 + DURATION_BASE
36
- TRIPLET_EIGHTH = 4 + DURATION_BASE
37
- TRIPLET_QUARTER = 10 + DURATION_BASE
38
- TRIPLET_HALF = 22 + DURATION_BASE
39
-
40
- TENUTO = 1.0
41
- ACCENT = 0.7
42
- STACCATO = 0.2
43
-
44
- attr_accessor :duration, :articulation, :duration_symbol
45
-
46
- def initialize(duration=:quarter, pitch=:c0, articulation=nil, duration_symbol=nil)
47
- @pitch_list = {c:C, bsharp:C,
48
- ds:DS, dflat:DS, csharp:DS,
49
- d:D,
50
- es:ES, eflat:ES, dsharp:DS,
51
- e:E, fs:FS, fflat:FS,
52
- f:F, esharp:F,
53
- gs:GS, gflat:GS, fsharp:GS,
54
- g:G,
55
- as:AS, aflat:AS, gsharp:AS,
56
- a:A,
57
- bs:BS, bflat:BS, asharp:BS,
58
- b:B, cs:CS, cflat:CS,
59
- rest:REST,
60
- }
61
-
62
- # Fix pitch first at this early timing
63
- if !pitch.to_s.match(/(.+)(\d)/).nil? then
64
- raise Exception.new "pitch #{pitch.to_s} is not defined." if !@pitch_list.keys.include?(Regexp.last_match(1).to_sym)
65
- @pitch = @pitch_list[Regexp.last_match(1).to_sym]
66
- if Regexp.last_match(2).to_i <= 4 then
67
- @octave = Regexp.last_match(2).to_i
68
- else
69
- raise Exception.new "Sorry only 0-4 octave range is supported."
70
- end
71
- else
72
- raise Exception.new "pitch #{pitch.to_s} is not defined." if !@pitch_list.keys.include?(pitch)
73
- @pitch = @pitch_list[pitch]
74
- @octave = 0
75
- end
76
-
77
- @duration = duration
78
- @articulation = articulation
79
- @duration_symbol = duration_symbol
80
- end
81
-
82
- def generate
83
- duration = get_actual_duration
84
-
85
- result = Array.new
86
- if @pitch==REST then
87
- @articuulation = 0
88
- else
89
- result << @pitch + 12 * @octave
90
- end
91
-
92
- articulation = Note.const_get(@articulation.upcase) if !@articulation.nil?
93
- if articulation.nil? then
94
- result << duration
95
- result << 63 # note stop
96
- elsif articulation == TENUTO then
97
- result << duration + 1
98
- else
99
- if (len(duration)*articulation).ceil > 0 then
100
- result << DURATION_BASE + (len(duration)*articulation).ceil
101
- result << 63 # note stop
102
- end
103
- if (len(duration)*(1.0 - articulation)).floor > 0 then
104
- result << DURATION_BASE + (len(duration)*(1.0-articulation)).floor
105
- end
106
- end
107
- result
108
- end
109
-
110
- private
111
- def len(duration)
112
- duration - DURATION_BASE
113
- end
114
-
115
- def get_actual_duration
116
- if !@duration_symbol.nil? then
117
- Note.const_get(@duration_symbol.upcase.to_s + "_" + @duration.upcase.to_s)
118
- else
119
- Note.const_get(@duration.upcase.to_s)
120
- end
121
- end
122
-
123
- end
124
- end
125
- end
@@ -1,278 +0,0 @@
1
- module Burn
2
- module Dsl
3
- class Scene < DslBase
4
- # Where to draw
5
- BG = 0 # background palette (0x00-0x0f)
6
- TEXT = 1 # background palette (0x00-0x0f)
7
- PALETTE_X1 = 5 # palette A for #screen and #paint method (whcih is a part background palette)
8
- PALETTE_X2 = 6
9
- PALETTE_X3 = 7
10
- PALETTE_Y1 = 9
11
- PALETTE_Y2 = 10
12
- PALETTE_Y3 = 11
13
- PALETTE_Z1 = 13
14
- PALETTE_Z2 = 14
15
- PALETTE_Z3 = 15
16
- SPRITE = 17 # sprite palette (0x10-0x1f)
17
-
18
- PALETTE_DEFAULT = 0
19
- PALETTE_X = 85 # palette expression for PPU Attribute table
20
- PALETTE_Y = 170 # palette expression for PPU Attribute table
21
- PALETTE_Z = 255 # palette expression for PPU Attribute table
22
-
23
- # Color Control
24
- WHITE = 0
25
- LIGHTBLUE = 1
26
- BLUE = 2
27
- PURPLE = 3
28
- PINK = 4
29
- RED = 5
30
- DEEPRED = 6
31
- ORANGE = 7
32
- LIGHTORANGE = 8
33
- DARKGREEN = 9
34
- GREEN = 10
35
- LIGHTGREEN = 11
36
- BLUEGREEN = 12
37
- GRAY = 13
38
- BLACK = 14
39
-
40
- # Light Control
41
- DARKEST = 0
42
- DARKER = 16
43
- LIGHTER = 32
44
- LIGHTEST = 48
45
-
46
- def initialize(resource_name, context)
47
- super(resource_name, context)
48
- end
49
-
50
- def label(string, x=0, y=1)
51
- @context.instance_exec {@code_blocks.push sprintf("put_str(NTADR(%d,%d),\"%s\");", x, y, string.upcase)}
52
- end
53
-
54
- def fade_in
55
- @context.instance_exec do
56
- [
57
- "ppu_on_all();",
58
- "screen_fade_in();"
59
- ].each {|p| @code_blocks.push p}
60
- end
61
- end
62
-
63
- def fade_out(sec=3)
64
- @context.instance_exec {@code_blocks.push "screen_fade_out(#{sec.to_s});"}
65
- end
66
-
67
- def color(palette, color, lightness=:lighter)
68
- palette=Scene.const_get(palette.upcase)
69
- color=Scene.const_get(color.upcase)
70
- lightness=Scene.const_get(lightness.upcase)
71
-
72
- @context.instance_exec {@code_blocks.push "pal_col(#{palette},0x#{(lightness+color).to_s(16)});"}
73
- end
74
-
75
- def play(song_title)
76
- @context.instance_exec do
77
- @global << "extern const unsigned char music_#{song_title}[];"
78
- @code_blocks << "music_play(music_#{song_title});"
79
- end
80
- end
81
-
82
- def stop
83
- @context.instance_exec {@code_blocks.push "music_stop();"}
84
- end
85
-
86
- def show(string, x=0, y=0, *args)
87
- @context.instance_exec(@resource_name) do |resource|
88
- nmi_plots = Array.new
89
- iChrCount=0
90
- isRequireArgs=false
91
- vname = resource+"_nmi_list"
92
- init_name = resource+"_nmi_init"
93
-
94
- string.split(//).each do |c|
95
- if c=='%' then
96
- isRequireArgs=true
97
- next
98
- end
99
- nmi_plots.push [x+iChrCount,y] if nmi_plots.index([x+iChrCount, y]).nil?
100
- if !isRequireArgs then
101
- @code_blocks.push sprintf("#{vname}[%d]=%s;", nmi_plots.index([x+iChrCount,y])*3+2, sprintf("%#x", c.bytes.to_a[0]-32))
102
- iChrCount+=1
103
- else
104
- if c=='d' then
105
- @code_blocks.push sprintf("#{vname}[%d]=0x10+%s;", nmi_plots.index([x+iChrCount,y])*3+2, args.shift)
106
- iChrCount+=1
107
- elsif c=='s' then
108
- args.shift.split(//).each do |d|
109
- nmi_plots.push [x+iChrCount,y] if nmi_plots.index([x+iChrCount, y]).nil?
110
- @code_blocks.push sprintf("#{vname}[%d]=%s;", nmi_plots.index([x+iChrCount,y])*3+2, sprintf("%#x", d.bytes.to_a[0]-32))
111
- iChrCount+=1
112
- end
113
- else
114
- raise "method #show can't take any data except for %d or %s. Please make sure you are passing correct 4th parameter."
115
- end
116
- end
117
- isRequireArgs=false
118
- end
119
-
120
- if nmi_plots.count>0 then
121
- # declaration for show method
122
- @global.push sprintf("static unsigned char #{vname}[%d*3];", nmi_plots.count)
123
- @global.push sprintf("const unsigned char #{init_name}[%d*3]={", nmi_plots.count)
124
- nmi_plots.each_with_index do |plot,i|
125
- @global.push sprintf("MSB(NTADR(%d,%d)),LSB(NTADR(%d,%d)),0%s", plot[0],plot[1],plot[0],plot[1],i<(nmi_plots.count-1)?",":"")
126
- end
127
- @global.push "};"
128
- @code_blocks.unshift "memcpy(#{vname},#{init_name},sizeof(#{init_name}));", sprintf("set_vram_update(%d,#{vname});", nmi_plots.count)
129
- end
130
-
131
- end
132
- end
133
-
134
- def wait(interval)
135
- #@context.instance_exec do
136
- # [
137
- # "while(1){",
138
- # "ppu_on_all();",
139
- # "delay(#{interval});",
140
- # "ppu_off();",
141
- # "break;",
142
- # "}"
143
- # ].each {|p| @code_blocks.push p}
144
- #end
145
- @context.instance_exec {@code_blocks.push "delay(#{interval});"}
146
- end
147
-
148
- def goto(scene_name)
149
- @context.instance_exec do
150
- [
151
- "ppu_off();",
152
- "set_vram_update(0,0);", #clear vram condition for #show
153
- "vram_adr(0x2000);", #clear nametable
154
- "vram_fill(0,1024);", #clear nametable
155
- "goto #{scene_name};"
156
- ].each {|p| @code_blocks.push p}
157
- end
158
- end
159
-
160
- def main_loop(rrb_source=nil)
161
- rrb_source = File.open("#{@resource_name}.rrb").read if rrb_source.nil? || File.extname(rrb_source) == "#{@resource_name}.rrb"
162
-
163
- # preprocess - for show method, all parameters after the 3rd parameter must be converted to String.
164
- rrb_source = rrb_source.lines.map{|line|
165
- if /^[\s\t]*show/ =~ line then
166
- line.chomp.split(",").each_with_index.map{|data, i|
167
- if i>2 then
168
- '"' + data + '"'
169
- else
170
- data
171
- end
172
- }.join(",")
173
- else
174
- line.chomp
175
- end
176
- }.join("\n")
177
-
178
- @context.instance_exec(@context,@resource_name) do |c, resource|
179
- # preprocess
180
- [
181
- "ppu_on_all();",
182
- "while(1){",
183
- "ppu_waitnmi(); //wait for next TV frame",
184
- ].each {|p| @code_blocks.push p}
185
-
186
- # parse ruby source code and process them partially
187
- p = Burn::Util::Pxes.new(Ripper.sexp(rrb_source),c,resource)
188
- #require 'pp'
189
- #pp p
190
- @code_blocks.push p.to_c
191
-
192
- # postprocess
193
- @code_blocks.push "}"
194
- end
195
-
196
- end
197
-
198
- def inline(code)
199
- @context.instance_exec {@code_blocks.push code}
200
- end
201
-
202
- #def sprite_set(x,y,tile_number,palette=0)
203
- # @context.instance_exec {@code_blocks.push "oam_spr(#{x},#{y},0x"+tile_number.to_s(16)+",#{palette},0);//0x40 is tile number, i&3 is palette"}
204
- #end
205
-
206
- def sprite(resource)
207
- @context.instance_exec {@code_blocks.push "sprite(&#{resource});"}
208
- end
209
-
210
- def screen(map, vars)
211
- @context.instance_exec(@resource_name) do |resource|
212
- current_char = nil
213
- consective_count = 0
214
- output = Array.new
215
- # the last character "\b" is just a dummy to finialize loop process
216
- (map.gsub(/(\r\n|\r|\n)/,"")+"\b").chars do |c|
217
- if current_char != c then
218
- if !current_char.nil? then
219
- if vars.keys.include?(current_char.to_sym) then
220
- output.push @pattern_table_index[vars[current_char.to_sym].to_sym] # user defined specific pattern
221
- else
222
- output.push 0 # blank pattern
223
- end
224
- # repeat to draw same pattern
225
- output.push 1, consective_count if consective_count>0
226
- end
227
- current_char = c
228
- consective_count = 0
229
- else
230
- consective_count += 1
231
- end
232
- end
233
- @global.push "const unsigned char screen_#{resource}["+(output.count+3).to_s+"]={0x01,"+output.map{|p| sprintf "0x%.2x", p}.join(",")+",0x01,0x00};"
234
- # "unrle_vram" means "decode Run Length Encoding and set them to vram".
235
- @code_blocks.push "unrle_vram(screen_#{resource},0x2020);" # previously used 0x2000 but it doesn't display very first line of screen.
236
- end
237
- end
238
-
239
- def paint(dest, palette)
240
- @context.instance_exec(@resource_name) do |resource|
241
- var_name="screen_#{resource}_color_#{@global.count}"
242
- @global.push "const unsigned char #{var_name}[6]={0x01,0x"+Scene.const_get(palette.upcase).to_s(16)+",0x01,"+sprintf("0x%.2x",dest.end-dest.begin)+",0x01,0x00};"
243
- @code_blocks.push "unrle_vram(#{var_name},0x"+(9152+dest.begin).to_s(16)+");" # 9152 is equivalent to 23C0
244
- end
245
- end
246
-
247
- def sound(effect_name)
248
- @context.instance_exec {@code_blocks.push "sfx_play(SFX_#{effect_name.upcase},0);"}
249
- end
250
-
251
-
252
- # vcall-ish methods
253
- def rand
254
- @context.instance_exec {@code_blocks.push "rand8()"}
255
- end
256
-
257
- alias_method :play_sound, :sound
258
- alias_method :play_music, :play
259
-
260
- # utility methods
261
- def range(x_from, y_from, x_to, y_to)
262
- x_to = x_from if x_to.nil?
263
- y_to = y_from if y_to.nil?
264
-
265
- plots = [x_from,y_from,x_to,y_to].map do |v|
266
- if v.is_a?(String) && v.end_with?("px") then # x:0-255, y:0:239
267
- v.to_i / 32
268
- else
269
- v.to_i / 4
270
- end
271
- end
272
-
273
- plots[1]*8+plots[0]..plots[3]*8+plots[2]
274
- end
275
-
276
- end
277
- end
278
- end