@@ -13,6 +13,8 @@ use std::fs::File;
1313use std:: io:: Write ;
1414use std:: path:: PathBuf ;
1515
16+ use neotron_common_bios:: video:: { Attr , TextBackgroundColour , TextForegroundColour } ;
17+
1618fn main ( ) {
1719 // Put `memory.x` in our output directory and ensure it's
1820 // on the linker search path.
@@ -55,4 +57,343 @@ fn main() {
5557
5658 // Write the file
5759 std:: fs:: write ( out. join ( "version.txt" ) , output) . expect ( "writing version file" ) ;
60+
61+ let logo = std:: fs:: read_to_string ( "src/logo.ansi" ) . expect ( "Can't open logo file" ) ;
62+ let mut output = Vec :: new ( ) ;
63+ let mut iter = logo. chars ( ) ;
64+ let mut attr = Attr :: new (
65+ TextForegroundColour :: WHITE ,
66+ TextBackgroundColour :: BLACK ,
67+ false ,
68+ ) ;
69+ let mut width = 0 ;
70+ loop {
71+ let Some ( ch) = iter. next ( ) else {
72+ break ;
73+ } ;
74+ if ch == '\u{001b}' {
75+ // ANSI escape
76+ if iter. next ( ) == Some ( '[' ) {
77+ // CSI
78+ let mut bright = false ;
79+ let mut accumulator = 0 ;
80+ loop {
81+ let next_ch = iter. next ( ) ;
82+ match ( next_ch, accumulator) {
83+ // Bright
84+ ( Some ( ';' | 'm' ) , 1 ) => {
85+ bright = true ;
86+ accumulator = 0 ;
87+ }
88+ // Background
89+ ( Some ( ';' | 'm' ) , 40 ) => {
90+ attr. set_bg ( TextBackgroundColour :: BLACK ) ;
91+ accumulator = 0 ;
92+ }
93+ ( Some ( ';' | 'm' ) , 41 ) => {
94+ attr. set_bg ( TextBackgroundColour :: DARK_RED ) ;
95+ accumulator = 0 ;
96+ }
97+ ( Some ( ';' | 'm' ) , 42 ) => {
98+ attr. set_bg ( TextBackgroundColour :: DARK_GREEN ) ;
99+ accumulator = 0 ;
100+ }
101+ ( Some ( ';' | 'm' ) , 43 ) => {
102+ attr. set_bg ( TextBackgroundColour :: YELLOW ) ;
103+ accumulator = 0 ;
104+ }
105+ ( Some ( ';' | 'm' ) , 44 ) => {
106+ attr. set_bg ( TextBackgroundColour :: BLUE ) ;
107+ accumulator = 0 ;
108+ }
109+ ( Some ( ';' | 'm' ) , 45 ) => {
110+ attr. set_bg ( TextBackgroundColour :: DARK_MAGENTA ) ;
111+ accumulator = 0 ;
112+ }
113+ ( Some ( ';' | 'm' ) , 46 ) => {
114+ attr. set_bg ( TextBackgroundColour :: DARK_CYAN ) ;
115+ accumulator = 0 ;
116+ }
117+ ( Some ( ';' | 'm' ) , 49 ) => {
118+ // Default
119+ attr. set_bg ( TextBackgroundColour :: BLACK ) ;
120+ accumulator = 0 ;
121+ }
122+ // Foreground
123+ ( Some ( ';' | 'm' ) , 30 ) => {
124+ attr. set_fg ( TextForegroundColour :: BLACK ) ;
125+ accumulator = 0 ;
126+ }
127+ ( Some ( ';' | 'm' ) , 31 ) => {
128+ attr. set_fg ( TextForegroundColour :: DARK_RED ) ;
129+ accumulator = 0 ;
130+ }
131+ ( Some ( ';' | 'm' ) , 32 ) => {
132+ attr. set_fg ( TextForegroundColour :: DARK_GREEN ) ;
133+ accumulator = 0 ;
134+ }
135+ ( Some ( ';' | 'm' ) , 33 ) => {
136+ attr. set_fg ( TextForegroundColour :: YELLOW ) ;
137+ accumulator = 0 ;
138+ }
139+ ( Some ( ';' | 'm' ) , 34 ) => {
140+ attr. set_fg ( TextForegroundColour :: BLUE ) ;
141+ accumulator = 0 ;
142+ }
143+ ( Some ( ';' | 'm' ) , 35 ) => {
144+ attr. set_fg ( TextForegroundColour :: DARK_MAGENTA ) ;
145+ accumulator = 0 ;
146+ }
147+ ( Some ( ';' | 'm' ) , 36 ) => {
148+ attr. set_fg ( TextForegroundColour :: DARK_CYAN ) ;
149+ accumulator = 0 ;
150+ }
151+ ( Some ( ';' | 'm' ) , 37 ) => {
152+ attr. set_fg ( TextForegroundColour :: GREY ) ;
153+ accumulator = 0 ;
154+ }
155+
156+ ( Some ( ';' | 'm' ) , 0 ) => {
157+ attr. set_fg ( TextForegroundColour :: GREY ) ;
158+ attr. set_bg ( TextBackgroundColour :: BLACK ) ;
159+ bright = false ;
160+ accumulator = 0 ;
161+ }
162+
163+ ( Some ( '0' ) , _) => {
164+ accumulator *= 10 ;
165+ }
166+ ( Some ( '1' ) , _) => {
167+ accumulator *= 10 ;
168+ accumulator += 1 ;
169+ }
170+ ( Some ( '2' ) , _) => {
171+ accumulator *= 10 ;
172+ accumulator += 2 ;
173+ }
174+ ( Some ( '3' ) , _) => {
175+ accumulator *= 10 ;
176+ accumulator += 3 ;
177+ }
178+ ( Some ( '4' ) , _) => {
179+ accumulator *= 10 ;
180+ accumulator += 4 ;
181+ }
182+ ( Some ( '5' ) , _) => {
183+ accumulator *= 10 ;
184+ accumulator += 5 ;
185+ }
186+ ( Some ( '6' ) , _) => {
187+ accumulator *= 10 ;
188+ accumulator += 6 ;
189+ }
190+ ( Some ( '7' ) , _) => {
191+ accumulator *= 10 ;
192+ accumulator += 7 ;
193+ }
194+ ( Some ( '8' ) , _) => {
195+ accumulator *= 10 ;
196+ accumulator += 8 ;
197+ }
198+ ( Some ( '9' ) , _) => {
199+ accumulator *= 10 ;
200+ accumulator += 9 ;
201+ }
202+ ( code, acc) => {
203+ panic ! (
204+ "Invalid ANSI sequence detected: code={:?}, acc={:?}" ,
205+ code, acc
206+ ) ;
207+ }
208+ }
209+ if next_ch == Some ( 'm' ) {
210+ // sequence is finished
211+ if bright {
212+ match attr. fg ( ) {
213+ TextForegroundColour :: DARK_RED => {
214+ attr. set_fg ( TextForegroundColour :: BRIGHT_RED ) ;
215+ }
216+ TextForegroundColour :: DARK_GREEN => {
217+ attr. set_fg ( TextForegroundColour :: BRIGHT_GREEN ) ;
218+ }
219+ TextForegroundColour :: YELLOW => {
220+ attr. set_fg ( TextForegroundColour :: BRIGHT_YELLOW ) ;
221+ }
222+ TextForegroundColour :: BLUE => {
223+ attr. set_fg ( TextForegroundColour :: BRIGHT_BLUE ) ;
224+ }
225+ TextForegroundColour :: DARK_MAGENTA => {
226+ attr. set_fg ( TextForegroundColour :: BRIGHT_MAGENTA ) ;
227+ }
228+ TextForegroundColour :: DARK_CYAN => {
229+ attr. set_fg ( TextForegroundColour :: BRIGHT_CYAN ) ;
230+ }
231+ TextForegroundColour :: GREY => {
232+ attr. set_fg ( TextForegroundColour :: WHITE ) ;
233+ }
234+ _ => {
235+ // Do nothing
236+ }
237+ }
238+ }
239+ break ;
240+ }
241+ }
242+ }
243+ } else if ch == '\n' {
244+ if width < 80 {
245+ // Only emit a new-line if we are not at the end of the line already
246+ output. push ( attr. as_u8 ( ) ) ;
247+ output. push ( b'\n' ) ;
248+ }
249+ width = 0 ;
250+ } else {
251+ width += 1 ;
252+ output. push ( attr. as_u8 ( ) ) ;
253+ output. push ( map_char_to_glyph ( ch) ) ;
254+ } ;
255+ }
256+ std:: fs:: write ( out. join ( "logo.bytes" ) , output) . expect ( "writing logo file" ) ;
257+ }
258+
259+ /// Convert a Unicode Scalar Value to a font glyph.
260+ ///
261+ /// Zero-width and modifier Unicode Scalar Values (e.g. `U+0301 COMBINING,
262+ /// ACCENT`) are not supported. Normalise your Unicode before calling
263+ /// this function.
264+ fn map_char_to_glyph ( input : char ) -> u8 {
265+ // This fixed table only works for the default font. When we support
266+ // changing font, we will need to plug-in a different table for each font.
267+ match input {
268+ '\u{0000}' ..='\u{007F}' => input as u8 ,
269+ '\u{00A0}' => 255 , // NBSP
270+ '\u{00A1}' => 173 , // ¡
271+ '\u{00A2}' => 189 , // ¢
272+ '\u{00A3}' => 156 , // £
273+ '\u{00A4}' => 207 , // ¤
274+ '\u{00A5}' => 190 , // ¥
275+ '\u{00A6}' => 221 , // ¦
276+ '\u{00A7}' => 245 , // §
277+ '\u{00A8}' => 249 , // ¨
278+ '\u{00A9}' => 184 , // ©
279+ '\u{00AA}' => 166 , // ª
280+ '\u{00AB}' => 174 , // «
281+ '\u{00AC}' => 170 , // ¬
282+ '\u{00AD}' => 240 , // SHY
283+ '\u{00AE}' => 169 , // ®
284+ '\u{00AF}' => 238 , // ¯
285+ '\u{00B0}' => 248 , // °
286+ '\u{00B1}' => 241 , // ±
287+ '\u{00B2}' => 253 , // ²
288+ '\u{00B3}' => 252 , // ³
289+ '\u{00B4}' => 239 , // ´
290+ '\u{00B5}' => 230 , // µ
291+ '\u{00B6}' => 244 , // ¶
292+ '\u{00B7}' => 250 , // ·
293+ '\u{00B8}' => 247 , // ¸
294+ '\u{00B9}' => 251 , // ¹
295+ '\u{00BA}' => 167 , // º
296+ '\u{00BB}' => 175 , // »
297+ '\u{00BC}' => 172 , // ¼
298+ '\u{00BD}' => 171 , // ½
299+ '\u{00BE}' => 243 , // ¾
300+ '\u{00BF}' => 168 , // ¿
301+ '\u{00C0}' => 183 , // À
302+ '\u{00C1}' => 181 , // Á
303+ '\u{00C2}' => 182 , // Â
304+ '\u{00C3}' => 199 , // Ã
305+ '\u{00C4}' => 142 , // Ä
306+ '\u{00C5}' => 143 , // Å
307+ '\u{00C6}' => 146 , // Æ
308+ '\u{00C7}' => 128 , // Ç
309+ '\u{00C8}' => 212 , // È
310+ '\u{00C9}' => 144 , // É
311+ '\u{00CA}' => 210 , // Ê
312+ '\u{00CB}' => 211 , // Ë
313+ '\u{00CC}' => 222 , // Ì
314+ '\u{00CD}' => 214 , // Í
315+ '\u{00CE}' => 215 , // Î
316+ '\u{00CF}' => 216 , // Ï
317+ '\u{00D0}' => 209 , // Ð
318+ '\u{00D1}' => 165 , // Ñ
319+ '\u{00D2}' => 227 , // Ò
320+ '\u{00D3}' => 224 , // Ó
321+ '\u{00D4}' => 226 , // Ô
322+ '\u{00D5}' => 229 , // Õ
323+ '\u{00D6}' => 153 , // Ö
324+ '\u{00D7}' => 158 , // ×
325+ '\u{00D8}' => 157 , // Ø
326+ '\u{00D9}' => 235 , // Ù
327+ '\u{00DA}' => 233 , // Ú
328+ '\u{00DB}' => 234 , // Û
329+ '\u{00DC}' => 154 , // Ü
330+ '\u{00DD}' => 237 , // Ý
331+ '\u{00DE}' => 232 , // Þ
332+ '\u{00DF}' => 225 , // ß
333+ '\u{00E0}' => 133 , // à
334+ '\u{00E1}' => 160 , // á
335+ '\u{00E2}' => 131 , // â
336+ '\u{00E3}' => 198 , // ã
337+ '\u{00E4}' => 132 , // ä
338+ '\u{00E5}' => 134 , // å
339+ '\u{00E6}' => 145 , // æ
340+ '\u{00E7}' => 135 , // ç
341+ '\u{00E8}' => 138 , // è
342+ '\u{00E9}' => 130 , // é
343+ '\u{00EA}' => 136 , // ê
344+ '\u{00EB}' => 137 , // ë
345+ '\u{00EC}' => 141 , // ì
346+ '\u{00ED}' => 161 , // í
347+ '\u{00EE}' => 140 , // î
348+ '\u{00EF}' => 139 , // ï
349+ '\u{00F0}' => 208 , // ð
350+ '\u{00F1}' => 164 , // ñ
351+ '\u{00F2}' => 149 , // ò
352+ '\u{00F3}' => 162 , // ó
353+ '\u{00F4}' => 147 , // ô
354+ '\u{00F5}' => 228 , // õ
355+ '\u{00F6}' => 148 , // ö
356+ '\u{00F7}' => 246 , // ÷
357+ '\u{00F8}' => 155 , // ø
358+ '\u{00F9}' => 151 , // ù
359+ '\u{00FA}' => 163 , // ú
360+ '\u{00FB}' => 150 , // û
361+ '\u{00FC}' => 129 , // ü
362+ '\u{00FD}' => 236 , // ý
363+ '\u{00FE}' => 231 , // þ
364+ '\u{00FF}' => 152 , // ÿ
365+ '\u{0131}' => 213 , // ı
366+ '\u{0192}' => 159 , // ƒ
367+ '\u{2017}' => 242 , // ‗
368+ '\u{2500}' => 196 , // ─
369+ '\u{2502}' => 179 , // │
370+ '\u{250C}' => 218 , // ┌
371+ '\u{2510}' => 191 , // ┐
372+ '\u{2514}' => 192 , // └
373+ '\u{2518}' => 217 , // ┘
374+ '\u{251C}' => 195 , // ├
375+ '\u{2524}' => 180 , // ┤
376+ '\u{252C}' => 194 , // ┬
377+ '\u{2534}' => 193 , // ┴
378+ '\u{253C}' => 197 , // ┼
379+ '\u{2550}' => 205 , // ═
380+ '\u{2551}' => 186 , // ║
381+ '\u{2554}' => 201 , // ╔
382+ '\u{2557}' => 187 , // ╗
383+ '\u{255A}' => 200 , // ╚
384+ '\u{255D}' => 188 , // ╝
385+ '\u{2560}' => 204 , // ╠
386+ '\u{2563}' => 185 , // ╣
387+ '\u{2566}' => 203 , // ╦
388+ '\u{2569}' => 202 , // ╩
389+ '\u{256C}' => 206 , // ╬
390+ '\u{2580}' => 223 , // ▀
391+ '\u{2584}' => 220 , // ▄
392+ '\u{2588}' => 219 , // █
393+ '\u{2591}' => 176 , // ░
394+ '\u{2592}' => 177 , // ▒
395+ '\u{2593}' => 178 , // ▓
396+ '\u{25A0}' => 254 , // ■
397+ _ => b'?' ,
398+ }
58399}
0 commit comments