gbtiles 0.1.1 → 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.
- checksums.yaml +4 -4
- data/README.md +22 -35
- data/bin/gbt +24 -0
- data/lib/gbtiles/gbm/cli/convert.rb +9 -1
- data/lib/gbtiles/gbm/export/asm/asm.h.erb +1 -1
- data/lib/gbtiles/gbm/export/asm/asm.rb +3 -0
- data/lib/gbtiles/gbm/export/asm/asm.s.erb +1 -1
- data/lib/gbtiles/gbm/import/gbm_file.rb +1 -1
- data/lib/gbtiles/gbm/map/objects/map_tile_data.rb +1 -3
- data/lib/gbtiles/gbr/cli/convert.rb +9 -1
- data/lib/gbtiles/gbr/export/asm/asm.h.erb +1 -1
- data/lib/gbtiles/gbr/export/asm/asm.rb +3 -0
- data/lib/gbtiles/gbr/export/asm/asm.s.erb +1 -1
- data/lib/gbtiles/gbr/import/gbr_file.rb +1 -1
- data/lib/gbtiles/gbr/tile_set/objects/tile_data.rb +1 -1
- data/lib/gbtiles/gbt/cli/convert.rb +58 -0
- data/lib/gbtiles/gbt/export/asm/asm.h.erb +11 -0
- data/lib/gbtiles/gbt/export/asm/asm.rb +63 -0
- data/lib/gbtiles/gbt/export/asm/asm.s.erb +20 -0
- data/lib/gbtiles/gbt/export/asm/channel.rb +156 -0
- data/lib/gbtiles/gbt/export/asm/channels/noise.rb +84 -0
- data/lib/gbtiles/gbt/export/asm/channels/pulse.rb +88 -0
- data/lib/gbtiles/gbt/export/asm/channels/wav.rb +105 -0
- data/lib/gbtiles/gbt/export/asm/converter.rb +37 -0
- data/lib/gbtiles/gbt/export/asm/effects/arpeggio.rb +16 -0
- data/lib/gbtiles/gbt/export/asm/effects/break_and_set_step.rb +16 -0
- data/lib/gbtiles/gbt/export/asm/effects/cut_note.rb +16 -0
- data/lib/gbtiles/gbt/export/asm/effects/jump.rb +16 -0
- data/lib/gbtiles/gbt/export/asm/effects/pan.rb +19 -0
- data/lib/gbtiles/gbt/export/asm/effects/speed.rb +22 -0
- data/lib/gbtiles/gbt/export/asm/effects/volume.rb +13 -0
- data/lib/gbtiles/gbt/import/mod_file.rb +65 -0
- data/lib/gbtiles/gbt/mod_data/mod_data.rb +21 -0
- data/lib/gbtiles/gbt/mod_data/pattern.rb +16 -0
- data/lib/gbtiles/gbt/mod_data/sample.rb +16 -0
- data/lib/gbtiles/helpers/data_type.rb +11 -0
- data/lib/gbtiles/version.rb +1 -1
- metadata +32 -38
@@ -0,0 +1,156 @@
|
|
1
|
+
require "gbtiles/gbt/export/asm/effects/arpeggio"
|
2
|
+
require "gbtiles/gbt/export/asm/effects/break_and_set_step"
|
3
|
+
require "gbtiles/gbt/export/asm/effects/cut_note"
|
4
|
+
require "gbtiles/gbt/export/asm/effects/jump"
|
5
|
+
require "gbtiles/gbt/export/asm/effects/pan"
|
6
|
+
require "gbtiles/gbt/export/asm/effects/speed"
|
7
|
+
require "gbtiles/gbt/export/asm/effects/volume"
|
8
|
+
|
9
|
+
module GBTiles
|
10
|
+
module GBT
|
11
|
+
module Export
|
12
|
+
module ASM
|
13
|
+
class Channel
|
14
|
+
include GBTiles::GBT::Export::ASM::Effects
|
15
|
+
|
16
|
+
NOTES = [
|
17
|
+
1712,1616,1524,1440,1356,1280,1208,1140,1076,1016, 960, 907,
|
18
|
+
856, 808, 762, 720, 678, 640, 604, 570, 538, 508, 480, 453,
|
19
|
+
428, 404, 381, 360, 339, 320, 302, 285, 269, 254, 240, 226,
|
20
|
+
214, 202, 190, 180, 170, 160, 151, 143, 135, 127, 120, 113,
|
21
|
+
107, 101, 95, 90, 85, 80, 75, 71, 67, 63, 60, 56,
|
22
|
+
53, 50, 47, 45, 42, 40, 37, 35, 33, 31, 30, 28
|
23
|
+
];
|
24
|
+
|
25
|
+
attr_accessor :channel_number
|
26
|
+
|
27
|
+
@data = [ 0, 0, 0, 0 ]
|
28
|
+
|
29
|
+
def data
|
30
|
+
@data
|
31
|
+
end
|
32
|
+
|
33
|
+
def data=(value)
|
34
|
+
if value.kind_of?(Array) then
|
35
|
+
@data = value
|
36
|
+
else
|
37
|
+
@data = value.unpack('CCCC')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize channel_number
|
42
|
+
@channel_number = channel_number
|
43
|
+
end
|
44
|
+
|
45
|
+
# Channel information
|
46
|
+
|
47
|
+
def is_pulse?
|
48
|
+
false
|
49
|
+
end
|
50
|
+
|
51
|
+
def is_wav?
|
52
|
+
false
|
53
|
+
end
|
54
|
+
|
55
|
+
def is_noise?
|
56
|
+
false
|
57
|
+
end
|
58
|
+
|
59
|
+
# Data
|
60
|
+
|
61
|
+
def sample_number
|
62
|
+
(@data[0] & 0xF0) | ((@data[2] & 0xF0) >> 4)
|
63
|
+
end
|
64
|
+
|
65
|
+
def sample_period
|
66
|
+
@data[1] | ((@data[0] & 0xF) << 8)
|
67
|
+
end
|
68
|
+
|
69
|
+
def is_empty_effect?
|
70
|
+
effect_number == 0 && effect_param == 0
|
71
|
+
end
|
72
|
+
|
73
|
+
def effect_number
|
74
|
+
@data[2] & 0xF
|
75
|
+
end
|
76
|
+
|
77
|
+
def effect_param
|
78
|
+
@data[3]
|
79
|
+
end
|
80
|
+
|
81
|
+
def effect_param_1
|
82
|
+
(@data[3] & 0xF0) >> 4
|
83
|
+
end
|
84
|
+
|
85
|
+
def effect_param_2
|
86
|
+
@data[3] & 0x0F
|
87
|
+
end
|
88
|
+
|
89
|
+
def effect_param_as_bcd
|
90
|
+
(((effect_param & 0xF0) >> 4) * 10) + (effect_param & 0xF)
|
91
|
+
end
|
92
|
+
|
93
|
+
def convert_volume
|
94
|
+
(effect_param == 64) ? 0xF : (effect_param >> 2);
|
95
|
+
end
|
96
|
+
|
97
|
+
# Amiga's 50 Hz to GB's 60 Hz
|
98
|
+
def convert_speed speed
|
99
|
+
speed * 60 / 50
|
100
|
+
end
|
101
|
+
|
102
|
+
def convert_effect
|
103
|
+
if effect_number == 0x0 then
|
104
|
+
return effect_arpeggio
|
105
|
+
end
|
106
|
+
|
107
|
+
if effect_number == 0xB then
|
108
|
+
return effect_jump
|
109
|
+
end
|
110
|
+
|
111
|
+
if effect_number == 0xC then
|
112
|
+
return effect_volume
|
113
|
+
end
|
114
|
+
|
115
|
+
if effect_number == 0xD then
|
116
|
+
return effect_break_and_set_step
|
117
|
+
end
|
118
|
+
|
119
|
+
if effect_number == 0xE && effect_param_1 == 0x8 then
|
120
|
+
return effect_pan
|
121
|
+
end
|
122
|
+
|
123
|
+
if effect_number == 0xE && effect_param_1 == 0xC then
|
124
|
+
return effect_cut_note
|
125
|
+
end
|
126
|
+
|
127
|
+
if effect_number == 0xF then
|
128
|
+
return effect_speed
|
129
|
+
end
|
130
|
+
|
131
|
+
throw "Unsupported effect"
|
132
|
+
end
|
133
|
+
|
134
|
+
def note_index
|
135
|
+
period = sample_period
|
136
|
+
|
137
|
+
if period <= 0 then
|
138
|
+
return -1
|
139
|
+
end
|
140
|
+
|
141
|
+
if !is_noise? then
|
142
|
+
if !period.between?(NOTES.last, NOTES.first) then
|
143
|
+
throw "Note `#{period}` out of bounds"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
NOTES.index(
|
148
|
+
NOTES.min_by { |x| (period - x).abs }
|
149
|
+
)
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# CHANNEL 4
|
2
|
+
|
3
|
+
require "gbtiles/gbt/export/asm/channel"
|
4
|
+
|
5
|
+
module GBTiles
|
6
|
+
module GBT
|
7
|
+
module Export
|
8
|
+
module ASM
|
9
|
+
module Channels
|
10
|
+
class Noise < GBTiles::GBT::Export::ASM::Channel
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
super(4)
|
14
|
+
end
|
15
|
+
|
16
|
+
def is_noise?
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
def convert
|
21
|
+
if sample_period == 0 then
|
22
|
+
convert_note_not_new
|
23
|
+
else
|
24
|
+
convert_note_new
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def convert_note_not_new
|
29
|
+
if is_empty_effect? then
|
30
|
+
return [0]
|
31
|
+
end
|
32
|
+
|
33
|
+
# Volume effect
|
34
|
+
if effect_number == 0xC then
|
35
|
+
return [
|
36
|
+
(1 << 5) | convert_volume
|
37
|
+
]
|
38
|
+
end
|
39
|
+
|
40
|
+
# Other effects
|
41
|
+
begin
|
42
|
+
converted = convert_effect
|
43
|
+
|
44
|
+
return [
|
45
|
+
(1 << 6) | converted[:number],
|
46
|
+
converted[:params]
|
47
|
+
]
|
48
|
+
rescue Exception => e
|
49
|
+
# Silence
|
50
|
+
end
|
51
|
+
|
52
|
+
return [0]
|
53
|
+
end
|
54
|
+
|
55
|
+
def convert_note_new
|
56
|
+
instrument = (sample_number - 16) & 0x1F
|
57
|
+
|
58
|
+
# Volume effect
|
59
|
+
if effect_number == 0xC then
|
60
|
+
return [
|
61
|
+
(1 << 7) | instrument,
|
62
|
+
convert_volume
|
63
|
+
]
|
64
|
+
end
|
65
|
+
|
66
|
+
# Other effects
|
67
|
+
begin
|
68
|
+
converted = convert_effect
|
69
|
+
|
70
|
+
return [
|
71
|
+
(1 << 7) | instrument,
|
72
|
+
(1 << 7) | converted[:number],
|
73
|
+
converted[:params]
|
74
|
+
]
|
75
|
+
rescue Exception => e
|
76
|
+
throw "Noise - Invalid command: #{e}"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# CHANNEL 1
|
2
|
+
# CHANNEL 2
|
3
|
+
|
4
|
+
require "gbtiles/gbt/export/asm/channel"
|
5
|
+
|
6
|
+
module GBTiles
|
7
|
+
module GBT
|
8
|
+
module Export
|
9
|
+
module ASM
|
10
|
+
module Channels
|
11
|
+
class Pulse < GBTiles::GBT::Export::ASM::Channel
|
12
|
+
|
13
|
+
def initialize(channel_number)
|
14
|
+
super(channel_number)
|
15
|
+
end
|
16
|
+
|
17
|
+
def is_pulse?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
def convert
|
22
|
+
if sample_period == 0 then
|
23
|
+
convert_note_not_new
|
24
|
+
else
|
25
|
+
convert_note_new
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def convert_note_not_new
|
30
|
+
instrument = sample_number & 3
|
31
|
+
|
32
|
+
if is_empty_effect? then
|
33
|
+
return [0]
|
34
|
+
end
|
35
|
+
|
36
|
+
# Volume effect
|
37
|
+
if effect_number == 0xC then
|
38
|
+
return [
|
39
|
+
(1 << 5) | convert_volume
|
40
|
+
]
|
41
|
+
end
|
42
|
+
|
43
|
+
# Other effects
|
44
|
+
begin
|
45
|
+
converted = convert_effect
|
46
|
+
|
47
|
+
return [
|
48
|
+
(1 << 6) | (instrument << 4) | converted[:number],
|
49
|
+
converted[:params]
|
50
|
+
]
|
51
|
+
rescue Exception => e
|
52
|
+
# Silence
|
53
|
+
end
|
54
|
+
|
55
|
+
return [0]
|
56
|
+
end
|
57
|
+
|
58
|
+
def convert_note_new
|
59
|
+
instrument = sample_number & 3
|
60
|
+
|
61
|
+
# Volume effect
|
62
|
+
if effect_number == 0xC then
|
63
|
+
return [
|
64
|
+
(1 << 7) | note_index,
|
65
|
+
(instrument << 4) | convert_volume
|
66
|
+
]
|
67
|
+
end
|
68
|
+
|
69
|
+
# Other effects
|
70
|
+
begin
|
71
|
+
converted = convert_effect
|
72
|
+
|
73
|
+
return [
|
74
|
+
(1 << 7) | note_index,
|
75
|
+
(1 << 7) | (instrument << 4) | converted[:number],
|
76
|
+
converted[:params]
|
77
|
+
]
|
78
|
+
rescue Exception => e
|
79
|
+
throw "Pulse - Invalid command: #{e}"
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# CHANNEL 3
|
2
|
+
|
3
|
+
require "gbtiles/gbt/export/asm/channel"
|
4
|
+
|
5
|
+
module GBTiles
|
6
|
+
module GBT
|
7
|
+
module Export
|
8
|
+
module ASM
|
9
|
+
module Channels
|
10
|
+
class Wav < GBTiles::GBT::Export::ASM::Channel
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
super(3)
|
14
|
+
end
|
15
|
+
|
16
|
+
def is_wav?
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
def convert_volume
|
21
|
+
case super
|
22
|
+
when 0..3
|
23
|
+
return 0
|
24
|
+
when 4..7
|
25
|
+
return 3
|
26
|
+
when 8..11
|
27
|
+
return 2
|
28
|
+
when 12..15
|
29
|
+
return 1
|
30
|
+
else
|
31
|
+
return 1
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def convert
|
36
|
+
if sample_period == 0 then
|
37
|
+
convert_note_not_new
|
38
|
+
else
|
39
|
+
convert_note_new
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def convert_note_not_new
|
44
|
+
if is_empty_effect? then
|
45
|
+
return [0]
|
46
|
+
end
|
47
|
+
|
48
|
+
# Volume effect
|
49
|
+
if effect_number == 0xC then
|
50
|
+
return [
|
51
|
+
(1 << 5) | convert_volume
|
52
|
+
]
|
53
|
+
end
|
54
|
+
|
55
|
+
# Other effects
|
56
|
+
begin
|
57
|
+
converted = convert_effect
|
58
|
+
|
59
|
+
return [
|
60
|
+
(1 << 6) | converted[:number],
|
61
|
+
converted[:params]
|
62
|
+
]
|
63
|
+
|
64
|
+
rescue Exception => e
|
65
|
+
# Silence
|
66
|
+
end
|
67
|
+
|
68
|
+
return [0]
|
69
|
+
end
|
70
|
+
|
71
|
+
def convert_note_new
|
72
|
+
instrument = (sample_number - 8) & 15
|
73
|
+
|
74
|
+
# Volume effect
|
75
|
+
if effect_number == 0xC then
|
76
|
+
return [
|
77
|
+
(1 << 7) | note_index,
|
78
|
+
(convert_volume << 4) | instrument
|
79
|
+
]
|
80
|
+
end
|
81
|
+
|
82
|
+
# Other effects
|
83
|
+
begin
|
84
|
+
converted = convert_effect
|
85
|
+
|
86
|
+
if (converted[:number] > 7) then
|
87
|
+
throw "Invalid command: only 0-7 allowed in this mode"
|
88
|
+
end
|
89
|
+
|
90
|
+
return [
|
91
|
+
(1 << 7) | note_index,
|
92
|
+
(1 << 7) | (converted_num << 4) | instrument,
|
93
|
+
converted_params
|
94
|
+
]
|
95
|
+
rescue Exception => e
|
96
|
+
throw "Wav - Invalid command: #{e}"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "gbtiles/gbt/export/asm/channels/pulse"
|
2
|
+
require "gbtiles/gbt/export/asm/channels/wav"
|
3
|
+
require "gbtiles/gbt/export/asm/channels/noise"
|
4
|
+
|
5
|
+
require "erb"
|
6
|
+
|
7
|
+
module GBTiles
|
8
|
+
module GBT
|
9
|
+
module Export
|
10
|
+
module ASM
|
11
|
+
class Converter
|
12
|
+
|
13
|
+
CHANNELS = {
|
14
|
+
1 => GBTiles::GBT::Export::ASM::Channels::Pulse.new(1),
|
15
|
+
2 => GBTiles::GBT::Export::ASM::Channels::Pulse.new(2),
|
16
|
+
3 => GBTiles::GBT::Export::ASM::Channels::Wav.new,
|
17
|
+
4 => GBTiles::GBT::Export::ASM::Channels::Noise.new
|
18
|
+
}
|
19
|
+
|
20
|
+
def convert data
|
21
|
+
CHANNELS[1].data = data[0..3]
|
22
|
+
CHANNELS[2].data = data[4..7]
|
23
|
+
CHANNELS[3].data = data[8..11]
|
24
|
+
CHANNELS[4].data = data[12..15]
|
25
|
+
|
26
|
+
[
|
27
|
+
CHANNELS[1].convert.map { |x| sprintf('0x%02X', x) }.join(', '),
|
28
|
+
CHANNELS[2].convert.map { |x| sprintf('0x%02X', x) }.join(', '),
|
29
|
+
CHANNELS[3].convert.map { |x| sprintf('0x%02X', x) }.join(', '),
|
30
|
+
CHANNELS[4].convert.map { |x| sprintf('0x%02X', x) }.join(', ')
|
31
|
+
].join(', ')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|