burn 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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