-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
asciitomapasm.rb
181 lines (154 loc) · 4.26 KB
/
asciitomapasm.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#!/usr/bin/env ruby
# Class to convert from ASCII-based txt files to GameBoy's Map/BG tile data.
# Generates 20x18 maps inside include files to ease adding them to ASM files .
# Uses my 'tileset.gbr' tiles, so would need changes to make it more generic.
# @author Kartones
class ASCIIToMapASM
MAX_ROWS = 18
MAX_COLS = 20
ASM_VALUES_PER_LINE = 10
DEFAULT_CHARACTER_TILE_NUM = 0
def initialize
@tiles_mapping = {}
setup_alphabetic_tiles
setup_other_tiles
end
def create_slides(directory=".")
valid_files = slide_filenames(directory)
puts "Add the following to your ASM code:" unless valid_files.length == 0
valid_files.each { |filename|
output_filename = [filename.split('.').first, "inc"].join('.').upcase
data = read_slide(filename, directory)
store(data, output_filename)
puts "INCLUDE \"#{output_filename}\""
}
end
# Make sure file is saved in ASCII/DOS mode (or don't use extended ASCII set/window frame characters)
def read_slide(filename="slide.txt", directory=".")
filepath = File.join(directory,filename)
raise "File #{filename} not found" unless File.exist?(filepath)
processed_lines = []
count = 0
file = File.open(filepath, "r")
while (line = file.gets)
raise "File #{filepath} exceeds maximum row size (#{MAX_ROWS})" if count > MAX_ROWS
count += 1
processed_lines.push(process_line(line.force_encoding(Encoding::ASCII_8BIT), count))
end
file.close
#bottom-padding, always MAX_ROWS columns
if processed_lines.length < MAX_ROWS
remaining = MAX_ROWS - processed_lines.length
remaining.times do
processed_lines.push(process_line(' ')) # will autofill with blanks
end
end
processed_lines.flatten
end
def store(contents=[], filename="map_data.inc", section_postfix="_DATA")
section_name = filename.split('.').first << section_postfix
file = File.new(filename, "w")
file.write(asm_data(contents, section_name))
file.close
end
private
def slide_filenames(directory=".")
files = []
Dir.new(directory).each { |file|
files.push(file) if file.split('.').last == "txt"
}
files
end
def asm_data(contents, section_name)
asm_data = "#{section_name}::\n"
index = 0
has_more = true
while has_more
chunk = contents.slice(index, ASM_VALUES_PER_LINE)
index += chunk.length
has_more = contents.length > index
asm_data << get_asm_line(chunk) << "\n"
end
asm_data
end
def get_asm_line(hex_values)
"DB " << hex_values.map { |value| "$#{value.upcase}" }.join(",")
end
def process_line(line, linenum=1)
processed = []
count = 0
line.each_char { |char|
unless (char.ord == 10 || char.ord == 13)
raise "Line #{linenum} exceeds maximum column size (#{MAX_COLS}) '#{char.ord}'" if count > MAX_COLS
count += 1
processed.push(process_character(char))
end
}
#right-padding, always MAX_COLS columns
if processed.length < MAX_COLS
remaining = MAX_COLS - processed.length
remaining.times do
processed.push(process_character(' '))
end
end
processed
end
def process_character(char)
output_char = @tiles_mapping.fetch(char.upcase, DEFAULT_CHARACTER_TILE_NUM)
"%02x" % (output_char != DEFAULT_CHARACTER_TILE_NUM ? output_char : window_char(char))
end
# Can't use non-US ASCII (7bit) characters as hash keys, so use a function
def window_char(char)
# @see http://www.theasciicode.com.ar/extended-ascii-code/box-drawing-character-single-line-upper-left-corner-ascii-code-218.html
case char.ord
when 179 # vert. line
70
when 196 # horiz. line
71
when 218 # upper left corner
72
when 191 # upper right corner
73
when 217 # lower right corner
74
when 192 # lower left corner
75
else
DEFAULT_CHARACTER_TILE_NUM
end
end
def setup_alphabetic_tiles
26.times do |index|
@tiles_mapping[(index + 65).chr] = index + 1
end
10.times do |index|
@tiles_mapping[(index + 48).chr] = index + 36
end
end
def setup_other_tiles
@tiles_mapping.merge!({
'.' => 27,
',' => 28,
':' => 29,
';' => 30,
'!' => 31,
'?' => 32,
'-' => 33,
'(' => 58,
')' => 59,
'[' => 60,
']' => 61,
'+' => 62,
'=' => 63,
'&' => 64,
'$' => 65,
'\'' => 66,
'"' => 67,
'/' => 68,
'|' => 69
})
end
end
begin
generator = ASCIIToMapASM.new.create_slides("slides")
end