-
Notifications
You must be signed in to change notification settings - Fork 0
/
template.8o
894 lines (713 loc) · 24 KB
/
template.8o
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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
##################################################################
##################################################################
#### General / Setup ####
##################################################################
##################################################################
# These features are all aliases, constants, and macros. They do
# not increase code size unless the macros are called.
:alias vJump0 v0
# Define tricky values as constants.
:const SUB_OP_UNDERFLOW 0 # vF's value when subtraction underflows
:const ADD_OP_OVERFLOW 1 # vF's value when addition overflows
:const MINUS_ONE 0xFF # -1 as the 8-bit two's complement
:macro add_u16_u8 x_hi_u16 x_lo_u16 y_lo_u8 {
#: Increment the x registers by the unsigned 8-bit value in y_lo_u8
#:
#: Params:
#: x_hi_u16 : vN
#: The hi byte of the destination; must be a register
#: x_lo_u16 : vN
#: The lo byte of the destination; must be a register
#: y_lo_u8 : vN or const u8
#: The hi byte of a 16 bit constant, or a register holding one
#: Clobbers:
#: vF
x_lo_u16 += lo_u16
x_hi_u16 += vF
}
:macro add_u16_u16 x_hi_u16 x_lo_u16 y_hi_u16 y_lo_u16 {
#: Add a 16 bit value to another and store the result in x_hi and x_lo
#:
#: Args:
#: x_hi_u16 : vN
#: The hi byte of the destination
#: x_lo_u16 : vN
#: The lo byte of the destination register
#: y_hi_u16 : vN or const u8
#: The hi byte of a 16 bit constant or a register holding one
#: y_lo_u16 : vN or const u8
#: The lo byte of a 16 bit constant or a register holding one
#: Clobbers:
#: vF
x_lo_u16 += y_lo_u16
x_hi_u16 += vF
x_hi_u16 += y_lo_u16
}
# General memory helpers
:macro unpack-and-increment LABEL hi_u16 lo_u16 {
#: Unpack LABEL to v0, v1 in long mode and offset it by the passed u16.
#:
#: Args:
#: LABEL : label
#: a label or calculation result for a location in memory
#: hi_u16 : a V register or an 8-bit constant
#: hi byte of a big endian unsigned 16 bit int or constant
#: lo_u16 : a V register or an 8-bit constant
#: lo byte of a big endian unsigned 16 bit int or constant
#: Clobbers:
#: vF
:unpack long LABEL
v1 += lo_u16
v0 += vF
v0 += hi_u16
}
# Time and feedback controls
:macro start_buzzer_though vN amount { vN := amount buzzer := vN }
:macro start_buzzer amount { vF := amount buzzer := vF }
:macro start_timer_through vN amount { vN := amount delay := vN }
:macro start_timer amount { vF := amount delay := vF }
##################################################################
##################################################################
#### General Rendering ####
##################################################################
##################################################################
:const HIREZ_WIDTH_PX 128
:const HIREZ_HEIGHT_PX 64
##################################################################
#### Current drawing state & persistence ####
##################################################################
:alias draw_x v5 #: The draw cursor's left edge
:alias draw_y v6 #: The draw cursor's top edge
:macro set-draw-coords-to X Y { draw_x := X draw_y := Y }
#: Set the current draw coordinates to the given value.
#:
#: Args:
#: X : vN or u8
#: The X coordinate to set
#: Y : vN or u8
#: The y coordinate to set
# Configurable color allows data to set the current color.
# See the font section futher down for more information.
:alias fg_color v7 #: Current foreground drawing color / planes
:alias bg_color v8 #: Current background drawing color / planes
:alias draw_reg_0 draw_x :alias draw_reg_end bg_color
:const PLANE_NONE 0 # Invisible
:const PLANE_1 1 # Plane 1
:const PLANE_2 2 # Plane 2
:const PLANE_3 3 # Both planes
:const COLOR_NONE PLANE_NONE
:const COLOR_WHITE PLANE_1
:const COLOR_RED PLANE_2
:const COLOR_GRAY PLANE_3
:macro set-fg-color SOURCE { fg_color := SOURCE }
#: Set the foreground plane mask to the passed value
#:
#: Args:
#: vN : vN or const u8
#: A register containing a valid plane mask.
:macro set-bg-color SOURCE { bg_color := SOURCE }
#: Set the background plane mask to the passed value
#:
#: Args:
#: SOURCE : vN or const u8
#: A register containing a valid plane mask.
: _set-active-color
# This implementation sacrifices space & cycles to avoid clobbering i.
# Total cycles: 7 (the <<= & :call in the wrapper macro + the body)
v0 <<= v0 # Total multiplication is * 4
jump0 _set-active-color-table
: _set-active-color-table
plane 0 return
plane 1 return
plane 2 return
plane 3 return
# # This implementation takes 5 cycles instead of 7 but clobbers i
# i := _color_nibble
# vF := 0xF0
# vF |= fg_color
# save vF - vF
# : _color_nibble
# plane 3
# return
:macro use-color vN { v0 <<= vN :call _set-active-color }
#: Set the plane mask to the value in vN
#:
#: Args:
#: vN : vN
#: A register containing a valid plane mask.
#: Clobbers:
#: v0, vF
:macro use-fg-color { use-color fg_color }
#: Set the current plane mask to the value in fg_color
#:
#: Clobbers:
#: v0, vF
:macro use-bg-color { use-color bg_color }
#: Set the plane mask to the value in bg_color
#:
#: Clobbers:
#: v0, vF
# Drawing state persistence between states / actions
: _drawing_state
: _drawing_state_xy
0x00 # X px
0x00 # Y px
: _drawing_state_colors
:byte { COLOR_GRAY } # Foreground color
:byte { COLOR_NONE } # Background color
: _drawing_state_end
: _default_drawing_state
: _default_drawing_state_xy
:byte { 0 }
:byte { 0 }
: _default_drawing_state_colors
:byte { COLOR_GRAY }
:byte { COLOR_NONE }
: _default_drawing_state_end
# Function bodies are inlinable for faster text drawing if needed
:macro _restore_drawing_state_at LABEL { i := LABEL load draw_reg_0 - draw_reg_end }
:macro _persist_drawing_state_at LABEL { i := LABEL save draw_reg_0 - draw_reg_end }
: restore-drawing-state
_restore_drawing_state_at _drawing_state
return
: persist-drawing-state
_persist_drawing_state_at _drawing_state
return
###################################################################
### Text rendering core ###
###################################################################
# This section contains the high-level description of how to render
# text.
# UI data we'll need
:const GLYPH_WIDTH_PX 4 # Usable glyph area
:const GLYPH_HEIGHT_PX 7 # Usable glyph area
:const GLYPH_TRACKING_PX 1 # Space between the characters
:const LINE_LEADING_PX 1 # Space after lines
:calc GLYPH_STEP_X_PX { GLYPH_WIDTH_PX + GLYPH_TRACKING_PX }
:calc GLYPH_STEP_Y_PX { GLYPH_HEIGHT_PX + LINE_LEADING_PX }
:const GLYPH_DATA_HEIGHT_PX 6 # Standard glyphs have this height
:calc GLYPH_DATA_LENGTH_BYTES { 2 * GLYPH_DATA_HEIGHT_PX }
:calc HIGHLIGHT_HEIGHT_PX { GLYPH_DATA_HEIGHT_PX + 1 }
# Where on screen the current message starts
:alias msg_start_x v9
:alias msg_start_y vA
# Current character & text mode
:alias current_byte_index vB
#: The current offset into the message.
:alias current_byte_value vC
#: The read value of the current byte.
:monitor current_byte_index "%i (decimal)"
:monitor current_byte_value "%c (ascii)"
:alias _msg_reg_0 msg_start_x :alias _msg_reg_end current_byte_value
# Todo: consider storing the decoded values in memory...
# useful if want to do layout.
# Universal control characters
:const CHAR_NULL 0x00 #: End of message
# "Block" boundaries for text to allow sparse text rendering
:const CHAR_SPACE 0x20 #: Boundary: start of early block
:const CHAR_SINGLEQUOTE 0x27 #: Boundary: end of early block
:const CHAR_A 0x41 #: Boundary: start of letters
:const CHAR_Z 0x5A #: Boundary: end of letters
#: ### Formatting control characters
:const CHAR_ESCAPE 0x5E #: The start of an escape sequence.
#: `^` in text is treated as an escape sequence opener.
#:
#: The following Control codes are supported:
:const CHAR_NEWLINE 0x0A #: '\n' in text, goes back to the
:const CHAR_B 0x42 #: Background control code
:const CHAR_F 0x46 #: Foreground control code
:const CHAR_D 0x44 #: "Restore defaults"
:macro _base10 NAME { :calc NAME { CALLS + 0x30 } }
_base10 CHAR_0
_base10 CHAR_1
_base10 CHAR_2
_base10 CHAR_3
_base10 CHAR_4
_base10 CHAR_5
_base10 CHAR_6
_base10 CHAR_7
_base10 CHAR_8
_base10 CHAR_9
:const STYLE_PLANE_0 CHAR_0
:const STYLE_PLANE_1 CHAR_1
:const STYLE_PLANE_2 CHAR_2
:const STYLE_PLANE_3 CHAR_3
# Character constants (check with `& 0x80`; 0b10000000 works too)
:const END_OF_STRING CHAR_NULL
# A coherent-ish block of chars values, '0' <= char <= 'Z'
:const MAINBLOCK_START CHAR_SINGLEQUOTE
:const MAINBLOCK_END CHAR_Z
:calc MAINBLOCK_SPAN { MAINBLOCK_END - MAINBLOCK_START }
: current_msg_state
#: A struct for persisting the current message state.
: _current_msg_position
0x00 # Msg start x
0x00 # Msg start Y
0x00 # current_byte_index
0x00 # current_byte_value
: _current_msg_position_end
# This has to be a label since we need to use a real
# memory address to persist the state between calls.
: restore-current-msg
#: Restore the current message pointer to i.
0xF0 0x00
: _current_msg_addr
0x00 0x00
return
:macro set-current-msg LABEL {
#: Set the current message to begin showing in a resumable way.
#:
#: Args:
#: LABEL : label
#: Which null-terminated message to set as active.
#:
#: Clobbers:
#: v0 - v1
#:
#: Returns : void
:unpack long LABEL # Store LABEL into v0, vN; long allows reading higher mem
i := long _current_msg_addr
save v0 - v1 # Uses rStart - rEnd form to avoid advancing
}
:macro peek-next-msg-byte vN {
#: Load the byte at current_byte_index in the current message to vN
#:
#: Args:
#: vN : vN
#: A register containing an offset into the message.
#: Clobbers:
#: i
#: Returns: u8
#: The value of the byte at offset vN from msg start.
:call restore-current-msg
i += current_byte_index
load vN - vN
}
:macro read-msg-byte vN { current_byte_index += 1 peek-next-msg-byte vN }
#: Read the next byte of the message, advancing the current byte index.
#: Args:
#: vN : vN
#: Where to read the current byte to.
#: Updates:
#: current_byte_index, i
#: Returns:
#: vN
:macro read-next-byte-as-color vN { read-msg-byte vN vN -= CHAR_0 }
#: Read the next byte of the message as a color, advancing the current byte index.
#: Args:
#: vN : vN
#: Where to read the color to.
#: Updates:
#: current_byte_index
#: Clobbers:
#: i
#: Returns:
#: vN
:macro show-msg START_X START_Y MSG_LABEL {
#: Set the draw cursor to the given X, Y and render a null-terminated message.
#:
#: Args:
#: START_X :
#: A X position to move the cursor to.
#: START_Y :
#: A Y position to move the cursor to.
#: MSG_LABEL :
#: A label-like token which points to a null-terminated message.
#:
#: Clobbers:
#: i, v0 - v3, vF
msg_start_x := START_X msg_start_y := START_Y
set-current-msg MSG_LABEL
:call _show-msg-render
}
: _show-msg-render
#: Render an entire null-terminated message.
#:
#: Args:
#: msg_start_x : vN
#: X position where messages should be shown on the screen
#: msg_start_y : vN
#: Y position where message should be shown on the screen.
#: Clobbers:
#: v0, current_byte_value, current_byte_index, vF
#: Updates:
#: draw_x, draw_y
# :breakpoint render
current_byte_index := 0
set-draw-coords-to msg_start_x msg_start_y
loop
peek-next-msg-byte current_byte_value
# Exit on end of message, no exceptions
while current_byte_value != END_OF_STRING
# :breakpoint decide
v0 := 0
if current_byte_value == CHAR_ESCAPE then v0 := 4 # instructions 2 long
if current_byte_value == CHAR_NEWLINE then v0 := 8 #
jump0 _byte_action_table
: _byte_action_table
:call render-visible-glyph jump _byte_action_table_after
:call handle-control jump _byte_action_table_after
:call handle-newline # jump _byte_action_table_after # Last jump redundant
: _byte_action_table_after
: _byte_loop_end
current_byte_index += 1
again
: _show-msg-render-end
return
:const TERMLIB_DEFAULT_FONT_STRINGMODES 1
# Macros defining the default font
# Macro used as `text "stringvalue"` will generate ascii bytes.
:stringmode text "\0\n !\"'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^m" {
:byte { CHAR }
}
# :stringmode text "^" { :byte CHAR_ESCAPE }
:stringmode text-offset "'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^" {
#( ( MAINBLOCK_START <= CHAR ) and ( CHAR <= MAINBLOCK_END ) ) *
:pointer { ( GLYPH_DATA_LENGTH_BYTES * 3 )
+ ( ( 3 + CHAR - MAINBLOCK_START ) * GLYPH_DATA_LENGTH_BYTES ) }
# :byte { ( mainblock-position >> 8 ) & 0xFF ) }
# :byte { mainblock-position & 0xFF ) }
}
# \0 !\"',./
:stringmode text-offset " !\"" {
:pointer { ( ( CHAR - CHAR_SPACE ) * GLYPH_DATA_LENGTH_BYTES ) }
}
# :stringmode text-offset "^" { :pointer long font_data_control }
####### Start of User code #######
: main
hires
:macro msg-screen MSG_LABEL {
clear
show-msg 0 0 MSG_LABEL
v0 := key
}
loop
msg-screen msg_title
msg-screen msg_all
again
: msg_title
text "\n\n"
text "^F3^B0 TERMLIB DEMO\n"
text " ^F3^B2 PRESS ANY KEY ^D\n"
text " ^F1^B3 ALL TEXT DYNAMIC! ^D\0"
: msg_all
text "^F0^B0 0^F1^B0 1^F2^B0 2^F3^B0 3\n"
text "^F0^B1 4^F1^B1 5^F2^B1 6^F3^B1 7\n"
text "^F0^B2 8^F1^B2 9^F2^B210^F3^B211\n"
text "^F0^B312^F1^B313^F2^B314^F3^B315^D\0"
####### End of User Code ######
# Render functions used by _show-msg-render
: handle-control
#: Handle the next byte as a control escape.
#:
#: Assumes non-printable / control byte in current_byte_value
#: Args:
#: current_byte_value : vN
#: a current byte which is assumed to be CHAR_ESCAPE
#: current_byte_index : vN
#: the current index in bytes into the string
#: Updates:
#: fg_color, bg_color, current_byte_value, current_char_index
#: Clobbers:
#: vF
#: Returns: void
read-msg-byte current_byte_value
if current_byte_value != CHAR_F then jump _handle-control-bg-color
read-next-byte-as-color fg_color
jump _handle-control-end
: _handle-control-bg-color
if current_byte_value != CHAR_B then jump _handle-control-check-default
read-next-byte-as-color bg_color
jump _handle-control-end
: _handle-control-check-default
if current_byte_value != CHAR_D then jump _handle-control-end
set-bg-color COLOR_NONE
set-fg-color COLOR_GRAY
use-fg-color
: _handle-control-end
return
: handle-newline
#: Move to the next line down.
#:
#: Updates:
#: draw_x, draw_y
#: Clobbers:
#: vF
#: Returns: void
draw_y += GLYPH_STEP_Y_PX
draw_x := msg_start_x
return
: render-visible-glyph
#: Render current_byte_value to the screen using the glyph table
#:
#: Args:
#: draw_x : vN
#: The screen x position to draw to in pixels
#: draw_y : vN
#: The screen y position to draw to in pixels
#: current_byte_value : vN
#: A value which is in font_offsets and font_data.
#: bg_color: vN
#: Which planes to draw the background on, if any.
#: fg_color: vN
#: Which planes to draw the foreground on, if any.
#: Clobbers:
#: i, v0 - v3, vF
#: Updates:
#: draw_x
# skip bg if no bg
if bg_color == 0 then jump _render_fg_glyph
use-bg-color
i := highlight_block_body
sprite draw_x draw_y HIGHLIGHT_HEIGHT_PX
# skip fg if no fg
: _render_fg_glyph
if fg_color == 0 then jump _render-visible-glyph-end
# Figure out which block we need: start or main
v2 := current_byte_value
if current_byte_value < MAINBLOCK_START begin
vF := CHAR_SPACE
else
vF := MAINBLOCK_START
end
v2 -= VF
# Convert from integer index into byte offset
v2 <<= v2
# Look up the raw offset value within the font
#i := long _font_offsets
0xF0 0x00 :pointer font_offsets
i += v2
load v2 - v3
# Combine with the base address for the font glyphs
unpack-and-increment font_data v2 v3
# Load the glyph data and render it
i := _render_glyph_address
save v0 - v1
0xF0 0x00
: _render_glyph_address
0x00 0x00
use-fg-color
sprite draw_x draw_y GLYPH_DATA_HEIGHT_PX
: _render-visible-glyph-end
draw_x += GLYPH_STEP_X_PX
return
###################################################################
### Font Data ###
###################################################################
: pixel_data
: highlight_block_prefix # 1-px wide pre block item
0x80 0x80 0x80 0x80 0x80 0x80 0x80
0x80 0x80 0x80 0x80 0x80 0x80 0x80
: highlight_block_body
# 0x78 0x78 0x78 0x78 0x78 0x78 0x78
# 0x78 0x78 0x78 0x78 0x78 0x78 0x78
0xF8 0xF8 0xF8 0xF8 0xF8 0xF8 0xF8
0xF8 0xF8 0xF8 0xF8 0xF8 0xF8 0xF8
: underline_cont
0x00 0x00 0x00 0x00 0x00 0x00 0xF0 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0xF0 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00
: underline_start
0x00 0x00 0x00 0x00 0x00 0x00 0xE0 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0xE0 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00
: font_offsets
text-offset " !\"'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ"
: font_data
# Based on Tom Thumb, used under CC0 Public Domain Dedication
# Original URL: https://robey.lag.net/2010/01/23/tiny-monospace-font.html
# ' ' 0x20
0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00
# '!' 0x21
0x00 0x10 0x10 0x10 0x00 0x10
0x00 0x10 0x10 0x10 0x00 0x10
# '"' 0x22
0x00 0x28 0x28 0x00 0x00 0x00
0x00 0x28 0x28 0x00 0x00 0x00
: font_data_mainblock
: font_data_singlequote
# "'" 0x27
0x00 0x10 0x10 0x00 0x00 0x00
0x00 0x10 0x10 0x00 0x00 0x00
: font_data_lparen
# '(' 0x28
0x00 0x20 0x40 0x40 0x40 0x20
0x00 0x20 0x40 0x40 0x40 0x20
: font_data_rparen
# ')' 0x29
0x00 0x40 0x20 0x20 0x20 0x40
0x00 0x40 0x20 0x20 0x20 0x40
: font_data_star
# '*' 0x2A
0x00 0x50 0x20 0x50 0x00 0x00
0x00 0x50 0x20 0x50 0x00 0x00
: font_data_plus
# '+' 0x2B
0x00 0x00 0x20 0x70 0x20 0x00
0x00 0x00 0x20 0x70 0x20 0x00
: font_data_comma
# ',' 0x2C
0x00 0x00 0x00 0x00 0x00 0x81
0x00 0x00 0x00 0x00 0x00 0x81
: font_data_dash
# '-', 0x2D
0x00 0x00 0x00 0x70 0x00 0x00
0x00 0x00 0x00 0x70 0x00 0x00
: font_data_period
# '.' 0x2E
0x00 0x00 0x00 0x00 0x00 0x01
0x00 0x00 0x00 0x00 0x00 0x01
: font_data_forward_slash
# '/' 0x2F
0x00 0x00 0x10 0x20 0x20 0x40
0x00 0x00 0x10 0x20 0x20 0x40
# '0' 0x30
0x00 0x30 0x50 0x50 0x50 0x60
0x00 0x30 0x50 0x50 0x50 0x60
# '1' 0x31
0x00 0x10 0x30 0x10 0x10 0x10
0x00 0x10 0x30 0x10 0x10 0x10
# '2' 0x32
0x00 0x60 0x10 0x20 0x40 0x70
0x00 0x60 0x10 0x20 0x40 0x70
# '3' 0x33
0x00 0x60 0x10 0x20 0x10 0x60
0x00 0x60 0x10 0x20 0x10 0x60
# '4' 0x34
0x00 0x50 0x50 0x70 0x10 0x10
0x00 0x50 0x50 0x70 0x10 0x10
# '5' 0x35
0x00 0x70 0x40 0x60 0x10 0x60
0x00 0x70 0x40 0x60 0x10 0x60
# '6' 0x36
0x00 0x30 0x40 0x70 0x50 0x70
0x00 0x30 0x40 0x70 0x50 0x70
# '7' 0x37
0x00 0x70 0x10 0x20 0x40 0x40
0x00 0x70 0x10 0x20 0x40 0x40
# '8' 0x38
0x00 0x70 0x50 0x70 0x50 0x70
0x00 0x70 0x50 0x70 0x50 0x70
# '9' 0x39
0x00 0x70 0x50 0x70 0x10 0x60
0x00 0x70 0x50 0x70 0x10 0x60
# ':' 0x3A
0x00 0x00 0x20 0x00 0x20 0x00
0x00 0x00 0x20 0x00 0x20 0x00
# ';' 0x3B
0x00 0x00 0x20 0x00 0x20 0x40
0x00 0x00 0x20 0x00 0x20 0x40
# '<' 0x3C
0x00 0x10 0x20 0x40 0x20 0x10
0x00 0x10 0x20 0x40 0x20 0x10
# '=' 0x3D
0x00 0x00 0x70 0x00 0x70 0x00
0x00 0x00 0x70 0x00 0x70 0x00
# '>' 0x3E
0x00 0x40 0x20 0x10 0x20 0x40
0x00 0x40 0x20 0x10 0x20 0x40
# '?' 0x3F
0x00 0x70 0x10 0x20 0x00 0x20
0x00 0x70 0x10 0x20 0x00 0x20
# '@' 0x40
0x00 0x70 0x70 0x70 0x70 0x70
0x00 0x70 0x70 0x70 0x70 0x70
# 'A' 0x41
0x00 0x20 0x50 0x70 0x50 0x50
0x00 0x20 0x50 0x70 0x50 0x50
# 'B' 0x42
0x00 0x60 0x50 0x60 0x50 0x60
0x00 0x60 0x50 0x60 0x50 0x60
# 'C' 0x43
0x00 0x30 0x40 0x40 0x40 0x30
0x00 0x30 0x40 0x40 0x40 0x30
# 'D' 0x44
0x00 0x60 0x50 0x50 0x50 0x60
0x00 0x60 0x50 0x50 0x50 0x60
# 'E' 0x45
0x00 0x70 0x40 0x70 0x40 0x70
0x00 0x70 0x40 0x70 0x40 0x70
# 'F' 0x46
0x00 0x70 0x40 0x70 0x40 0x40
0x00 0x70 0x40 0x70 0x40 0x40
# 'G' 0x47
0x00 0x30 0x40 0x70 0x50 0x30
0x00 0x30 0x40 0x70 0x50 0x30
# 'H' 0x48
0x00 0x50 0x50 0x70 0x50 0x50
0x00 0x50 0x50 0x70 0x50 0x50
# 'I' 0x49
0x00 0x70 0x20 0x20 0x20 0x70
0x00 0x70 0x20 0x20 0x20 0x70
# 'J' 0x4A
0x00 0x10 0x10 0x10 0x50 0x20
0x00 0x10 0x10 0x10 0x50 0x20
# 'K' 0x4B
0x00 0x50 0x50 0x60 0x50 0x50
0x00 0x50 0x50 0x60 0x50 0x50
# 'L' 0x4C
0x00 0x40 0x40 0x40 0x40 0x70
0x00 0x40 0x40 0x40 0x40 0x70
# 'M' 0x4D
0x00 0x50 0x70 0x70 0x50 0x50
0x00 0x50 0x70 0x70 0x50 0x50
# 'N' 0x4E
0x00 0x50 0x70 0x70 0x70 0x50
0x00 0x50 0x70 0x70 0x70 0x50
# 'O' 0x4F
0x00 0x20 0x50 0x50 0x50 0x20
0x00 0x20 0x50 0x50 0x50 0x20
# 'P' 0x50
0x00 0x60 0x50 0x60 0x40 0x40
0x00 0x60 0x50 0x60 0x40 0x40
# 'Q' 0x51
0x00 0x20 0x50 0x50 0x70 0x30
0x00 0x20 0x50 0x50 0x70 0x30
# 'R' 0x52
0x00 0x60 0x50 0x70 0x60 0x50
0x00 0x60 0x50 0x70 0x60 0x50
# 'S' 0x53
0x00 0x30 0x40 0x20 0x10 0x60
0x00 0x30 0x40 0x20 0x10 0x60
# 'T' 0x54
0x00 0x70 0x20 0x20 0x20 0x20
0x00 0x70 0x20 0x20 0x20 0x20
# 'U' 0x55
0x00 0x50 0x50 0x50 0x50 0x30
0x00 0x50 0x50 0x50 0x50 0x30
# 'V' 0x56
0x00 0x50 0x50 0x50 0x20 0x20
0x00 0x50 0x50 0x50 0x20 0x20
# 'W' 0x57
0x00 0x50 0x50 0x70 0x70 0x50
0x00 0x50 0x50 0x70 0x70 0x50
# 'X' 0x58
0x00 0x50 0x50 0x20 0x50 0x50
0x00 0x50 0x50 0x20 0x50 0x50
# 'Y' 0x59
0x00 0x50 0x50 0x20 0x20 0x20
0x00 0x50 0x50 0x20 0x20 0x20
# 'Z' 0x5A
0x00 0x70 0x10 0x20 0x40 0x70
0x00 0x70 0x10 0x20 0x40 0x70
: font_data_control
# Leftovers from before deciding against bash escape codes
# End of mainblock
# '[' 0x5B
# 0x00 0x30 0x20 0x20 0x20 0x30
# 0x00 0x30 0x20 0x20 0x20 0x30
# # 'm' filler
# 0x00 0x00 0x00 0x00 0x00 0x00
# 0x00 0x00 0x00 0x00 0x00 0x00
# '^' 0x5E
0x00 0x00 0x10 0x28 0x00 0x00
0x00 0x00 0x10 0x28 0x00 0x00
# # '~' 0x7E
# 0x00 0x00 0x00 0x28 0x50 0x00
# 0x00 0x00 0x00 0x28 0x50 0x00
# '\\' # Filler for "\\" escape code.
# 0x00 0x00 0x00 0x00 0x00 0x00
# 0x00 0x00 0x00 0x00 0x00 0x00