forked from floooh/sokol
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsokol_debugtext.h
4567 lines (4272 loc) · 244 KB
/
sokol_debugtext.h
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
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#if defined(SOKOL_IMPL) && !defined(SOKOL_DEBUGTEXT_IMPL)
#define SOKOL_DEBUGTEXT_IMPL
#endif
#ifndef SOKOL_DEBUGTEXT_INCLUDED
/*
sokol_debugtext.h - simple ASCII debug text rendering on top of sokol_gfx.h
Project URL: https://github.com/floooh/sokol
Do this:
#define SOKOL_IMPL or
#define SOKOL_DEBUGTEXT_IMPL
before you include this file in *one* C or C++ file to create the
implementation.
The following defines are used by the implementation to select the
platform-specific embedded shader code (these are the same defines as
used by sokol_gfx.h and sokol_app.h):
SOKOL_GLCORE
SOKOL_GLES3
SOKOL_D3D11
SOKOL_METAL
SOKOL_WGPU
...optionally provide the following macros to override defaults:
SOKOL_VSNPRINTF - the function name of an alternative vsnprintf() function (default: vsnprintf)
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
SOKOL_DEBUGTEXT_API_DECL - public function declaration prefix (default: extern)
SOKOL_API_DECL - same as SOKOL_DEBUGTEXT_API_DECL
SOKOL_API_IMPL - public function implementation prefix (default: -)
SOKOL_UNREACHABLE() - a guard macro for unreachable code (default: assert(false))
If sokol_debugtext.h is compiled as a DLL, define the following before
including the declaration or implementation:
SOKOL_DLL
On Windows, SOKOL_DLL will define SOKOL_DEBUGTEXT_API_DECL as __declspec(dllexport)
or __declspec(dllimport) as needed.
Include the following headers before including sokol_debugtext.h:
sokol_gfx.h
FEATURES AND CONCEPTS
=====================
- renders 8-bit ASCII text as fixed-size 8x8 pixel characters
- comes with 6 embedded 8-bit home computer fonts (each taking up 2 KBytes)
- easily plug in your own fonts
- create multiple contexts for rendering text in different layers or render passes
STEP BY STEP
============
--- to initialize sokol-debugtext, call sdtx_setup() *after* initializing
sokol-gfx:
sdtx_setup(&(sdtx_desc_t){ ... });
To see any warnings and errors, you should always install a logging callback.
The easiest way is via sokol_log.h:
#include "sokol_log.h"
sdtx_setup(&(sdtx_desc_t){
.logger.func = slog_func,
});
--- configure sokol-debugtext by populating the sdtx_desc_t struct:
.context_pool_size (default: 8)
The max number of text contexts that can be created.
.printf_buf_size (default: 4096)
The size of the internal text formatting buffer used by
sdtx_printf() and sdtx_vprintf().
.fonts (default: none)
An array of sdtx_font_desc_t structs used to configure the
fonts that can be used for rendering. To use all builtin
fonts call sdtx_setup() like this (in C99):
sdtx_setup(&(sdtx_desc_t){
.fonts = {
[0] = sdtx_font_kc853(),
[1] = sdtx_font_kc854(),
[2] = sdtx_font_z1013(),
[3] = sdtx_font_cpc(),
[4] = sdtx_font_c64(),
[5] = sdtx_font_oric()
}
});
For documentation on how to use you own font data, search
below for "USING YOUR OWN FONT DATA".
.context
The setup parameters for the default text context. This will
be active right after sdtx_setup(), or when calling
sdtx_set_context(SDTX_DEFAULT_CONTEXT):
.max_commands (default: 4096)
The max number of render commands that can be recorded
into the internal command buffer. This directly translates
to the number of render layer changes in a single frame.
.char_buf_size (default: 4096)
The number of characters that can be rendered per frame in this
context, defines the size of an internal fixed-size vertex
buffer. Any additional characters will be silently ignored.
.canvas_width (default: 640)
.canvas_height (default: 480)
The 'virtual canvas size' in pixels. This defines how big
characters will be rendered relative to the default framebuffer
dimensions. Each character occupies a grid of 8x8 'virtual canvas
pixels' (so a virtual canvas size of 640x480 means that 80x60 characters
fit on the screen). For rendering in a resizeable window, you
should dynamically update the canvas size in each frame by
calling sdtx_canvas(w, h).
.tab_width (default: 4)
The width of a tab character in number of character cells.
.color_format (default: 0)
.depth_format (default: 0)
.sample_count (default: 0)
The pixel format description for the default context needed
for creating the context's sg_pipeline object. When
rendering to the default framebuffer you can leave those
zero-initialized, in this case the proper values will be
filled in by sokol-gfx. You only need to provide non-default
values here when rendering to render targets with different
pixel format attributes than the default framebuffer.
--- Before starting to render text, optionally call sdtx_canvas() to
dynamically resize the virtual canvas. This is recommended when
rendering to a resizeable window. The virtual canvas size can
also be used to scale text in relation to the display resolution.
Examples when using sokol-app:
- to render characters at 8x8 'physical pixels':
sdtx_canvas(sapp_width(), sapp_height());
- to render characters at 16x16 physical pixels:
sdtx_canvas(sapp_width()/2.0f, sapp_height()/2.0f);
Do *not* use integer math here, since this will not look nice
when the render target size isn't divisible by 2.
--- Optionally define the origin for the character grid with:
sdtx_origin(x, y);
The provided coordinates are in character grid cells, not in
virtual canvas pixels. E.g. to set the origin to 2 character tiles
from the left and top border:
sdtx_origin(2, 2);
You can define fractions, e.g. to start rendering half
a character tile from the top-left corner:
sdtx_origin(0.5f, 0.5f);
--- Optionally set a different font by calling:
sdtx_font(font_index)
sokol-debugtext provides 8 font slots which can be populated
with the builtin fonts or with user-provided font data, so
'font_index' must be a number from 0 to 7.
--- Position the text cursor with one of the following calls. All arguments
are in character grid cells as floats and relative to the
origin defined with sdtx_origin():
sdtx_pos(x, y) - sets absolute cursor position
sdtx_pos_x(x) - only set absolute x cursor position
sdtx_pos_y(y) - only set absolute y cursor position
sdtx_move(x, y) - move cursor relative in x and y direction
sdtx_move_x(x) - move cursor relative only in x direction
sdtx_move_y(y) - move cursor relative only in y direction
sdtx_crlf() - set cursor to beginning of next line
(same as sdtx_pos_x(0) + sdtx_move_y(1))
sdtx_home() - resets the cursor to the origin
(same as sdtx_pos(0, 0))
--- Set a new text color with any of the following functions:
sdtx_color3b(r, g, b) - RGB 0..255, A=255
sdtx_color3f(r, g, b) - RGB 0.0f..1.0f, A=1.0f
sdtx_color4b(r, g, b, a) - RGBA 0..255
sdtx_color4f(r, g, b, a) - RGBA 0.0f..1.0f
sdtx_color1i(uint32_t rgba) - ABGR (0xAABBGGRR)
--- Output 8-bit ASCII text with the following functions:
sdtx_putc(c) - output a single character
sdtx_puts(str) - output a null-terminated C string, note that
this will *not* append a newline (so it behaves
differently than the CRT's puts() function)
sdtx_putr(str, len) - 'put range' output the first 'len' characters of
a C string or until the zero character is encountered
sdtx_printf(fmt, ...) - output with printf-formatting, note that you
can inject your own printf-compatible function
by overriding the SOKOL_VSNPRINTF define before
including the implementation
sdtx_vprintf(fmt, args) - same as sdtx_printf() but with the arguments
provided in a va_list
- Note that the text will not yet be rendered, only recorded for rendering
at a later time, the actual rendering happens when sdtx_draw() is called
inside a sokol-gfx render pass.
- This means also you can output text anywhere in the frame, it doesn't
have to be inside a render pass.
- Note that character codes <32 are reserved as control characters
and won't render anything. Currently only the following control
characters are implemented:
\r - carriage return (same as sdtx_pos_x(0))
\n - carriage return + line feed (same as stdx_crlf())
\t - a tab character
--- You can 'record' text into render layers, this allows to mix/interleave
sokol-debugtext rendering with other rendering operations inside
sokol-gfx render passes. To start recording text into a different render
layer, call:
sdtx_layer(int layer_id)
...outside a sokol-gfx render pass.
--- finally, from within a sokol-gfx render pass, call:
sdtx_draw()
...for non-layered rendering, or to draw a specific layer:
sdtx_draw_layer(int layer_id)
NOTE that sdtx_draw() is equivalent to:
sdtx_draw_layer(0)
...so sdtx_draw() will *NOT* render all text layers, instead it will
only render the 'default layer' 0.
--- at the end of a frame (defined by the call to sg_commit()), sokol-debugtext
will rewind all contexts:
- the internal vertex index is set to 0
- the internal command index is set to 0
- the current layer id is set to 0
- the current font is set to 0
- the cursor position is reset
RENDERING WITH MULTIPLE CONTEXTS
================================
Use multiple text contexts if you need to render debug text in different
sokol-gfx render passes, or want to render text to different layers
in the same render pass, each with its own set of parameters.
To create a new text context call:
sdtx_context ctx = sdtx_make_context(&(sdtx_context_desc_t){ ... });
The creation parameters in the sdtx_context_desc_t struct are the same
as already described above in the sdtx_setup() function:
.char_buf_size -- max number of characters rendered in one frame, default: 4096
.canvas_width -- the initial virtual canvas width, default: 640
.canvas_height -- the initial virtual canvas height, default: 400
.tab_width -- tab width in number of characters, default: 4
.color_format -- color pixel format of target render pass
.depth_format -- depth pixel format of target render pass
.sample_count -- MSAA sample count of target render pass
To make a new context the active context, call:
sdtx_set_context(ctx)
...and after that call the text output functions as described above, and
finally, inside a sokol-gfx render pass, call sdtx_draw() to actually
render the text for this context.
A context keeps track of the following parameters:
- the active font
- the virtual canvas size
- the origin position
- the current cursor position
- the current tab width
- the current color
- and the current layer-id
You can get the currently active context with:
sdtx_get_context()
To make the default context current, call sdtx_set_context() with the
special SDTX_DEFAULT_CONTEXT handle:
sdtx_set_context(SDTX_DEFAULT_CONTEXT)
Alternatively, use the function sdtx_default_context() to get the default
context handle:
sdtx_set_context(sdtx_default_context());
To destroy a context, call:
sdtx_destroy_context(ctx)
If a context is set as active that no longer exists, all sokol-debugtext
functions that require an active context will silently fail.
You can directly draw the recorded text in a specific context without
setting the active context:
sdtx_context_draw(ctx)
sdtx_context_draw_layer(ctx, layer_id)
USING YOUR OWN FONT DATA
========================
Instead of the built-in fonts you can also plug your own font data
into sokol-debugtext by providing one or several sdtx_font_desc_t
structures in the sdtx_setup call.
For instance to use a built-in font at slot 0, and a user-font at
font slot 1, the sdtx_setup() call might look like this:
sdtx_setup(&sdtx_desc_t){
.fonts = {
[0] = sdtx_font_kc853(),
[1] = {
.data = {
.ptr = my_font_data,
.size = sizeof(my_font_data)
},
.first_char = ...,
.last_char = ...
}
}
});
Where 'my_font_data' is a byte array where every character is described
by 8 bytes arranged like this:
bits
7 6 5 4 3 2 1 0
. . . X X . . . byte 0: 0x18
. . X X X X . . byte 1: 0x3C
. X X . . X X . byte 2: 0x66
. X X . . X X . byte 3: 0x66
. X X X X X X . byte 4: 0x7E
. X X . . X X . byte 5: 0x66
. X X . . X X . byte 6: 0x66
. . . . . . . . byte 7: 0x00
A complete font consists of 256 characters, resulting in 2048 bytes for
the font data array (but note that the character codes 0..31 will never
be rendered).
If you provide such a complete font data array, you can drop the .first_char
and .last_char initialization parameters since those default to 0 and 255,
note that you can also use the SDTX_RANGE() helper macro to build the
.data item:
sdtx_setup(&sdtx_desc_t){
.fonts = {
[0] = sdtx_font_kc853(),
[1] = {
.data = SDTX_RANGE(my_font_data)
}
}
});
If the font doesn't define all 256 character tiles, or you don't need an
entire 256-character font and want to save a couple of bytes, use the
.first_char and .last_char initialization parameters to define a sub-range.
For instance if the font only contains the characters between the Space
(ASCII code 32) and uppercase character 'Z' (ASCII code 90):
sdtx_setup(&sdtx_desc_t){
.fonts = {
[0] = sdtx_font_kc853(),
[1] = {
.data = SDTX_RANGE(my_font_data),
.first_char = 32, // could also write ' '
.last_char = 90 // could also write 'Z'
}
}
});
Character tiles that haven't been defined in the font will be rendered
as a solid 8x8 quad.
MEMORY ALLOCATION OVERRIDE
==========================
You can override the memory allocation functions at initialization time
like this:
void* my_alloc(size_t size, void* user_data) {
return malloc(size);
}
void my_free(void* ptr, void* user_data) {
free(ptr);
}
...
sdtx_setup(&(sdtx_desc_t){
// ...
.allocator = {
.alloc_fn = my_alloc,
.free_fn = my_free,
.user_data = ...;
}
});
...
If no overrides are provided, malloc and free will be used.
ERROR REPORTING AND LOGGING
===========================
To get any logging information at all you need to provide a logging callback in the setup call,
the easiest way is to use sokol_log.h:
#include "sokol_log.h"
sdtx_setup(&(sdtx_desc_t){
// ...
.logger.func = slog_func
});
To override logging with your own callback, first write a logging function like this:
void my_log(const char* tag, // e.g. 'sdtx'
uint32_t log_level, // 0=panic, 1=error, 2=warn, 3=info
uint32_t log_item_id, // SDTX_LOGITEM_*
const char* message_or_null, // a message string, may be nullptr in release mode
uint32_t line_nr, // line number in sokol_debugtext.h
const char* filename_or_null, // source filename, may be nullptr in release mode
void* user_data)
{
...
}
...and then setup sokol-debugtext like this:
sdtx_setup(&(sdtx_desc_t){
.logger = {
.func = my_log,
.user_data = my_user_data,
}
});
The provided logging function must be reentrant (e.g. be callable from
different threads).
If you don't want to provide your own custom logger it is highly recommended to use
the standard logger in sokol_log.h instead, otherwise you won't see any warnings or
errors.
LICENSE
=======
zlib/libpng license
Copyright (c) 2020 Andre Weissflog
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the
use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#define SOKOL_DEBUGTEXT_INCLUDED (1)
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h> // size_t
#include <stdarg.h> // va_list
#if !defined(SOKOL_GFX_INCLUDED)
#error "Please include sokol_gfx.h before sokol_debugtext.h"
#endif
#if defined(SOKOL_API_DECL) && !defined(SOKOL_DEBUGTEXT_API_DECL)
#define SOKOL_DEBUGTEXT_API_DECL SOKOL_API_DECL
#endif
#ifndef SOKOL_DEBUGTEXT_API_DECL
#if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_DEBUGTEXT_IMPL)
#define SOKOL_DEBUGTEXT_API_DECL __declspec(dllexport)
#elif defined(_WIN32) && defined(SOKOL_DLL)
#define SOKOL_DEBUGTEXT_API_DECL __declspec(dllimport)
#else
#define SOKOL_DEBUGTEXT_API_DECL extern
#endif
#endif
#if defined(__GNUC__)
#define SOKOL_DEBUGTEXT_PRINTF_ATTR __attribute__((format(printf, 1, 2)))
#else
#define SOKOL_DEBUGTEXT_PRINTF_ATTR
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
sdtx_log_item_t
Log items are defined via X-Macros, and expanded to an
enum 'sdtx_log_item' - and in debug mode only - corresponding strings.
Used as parameter in the logging callback.
*/
#define _SDTX_LOG_ITEMS \
_SDTX_LOGITEM_XMACRO(OK, "Ok") \
_SDTX_LOGITEM_XMACRO(MALLOC_FAILED, "memory allocation failed") \
_SDTX_LOGITEM_XMACRO(ADD_COMMIT_LISTENER_FAILED, "sg_add_commit_listener() failed") \
_SDTX_LOGITEM_XMACRO(COMMAND_BUFFER_FULL, "command buffer full (adjust via sdtx_context_desc_t.max_commands)") \
_SDTX_LOGITEM_XMACRO(CONTEXT_POOL_EXHAUSTED, "context pool exhausted (adjust via sdtx_desc_t.context_pool_size)") \
_SDTX_LOGITEM_XMACRO(CANNOT_DESTROY_DEFAULT_CONTEXT, "cannot destroy default context") \
#define _SDTX_LOGITEM_XMACRO(item,msg) SDTX_LOGITEM_##item,
typedef enum sdtx_log_item_t {
_SDTX_LOG_ITEMS
} sdtx_log_item_t;
#undef _SDTX_LOGITEM_XMACRO
/*
sdtx_logger_t
Used in sdtx_desc_t to provide a custom logging and error reporting
callback to sokol-debugtext.
*/
typedef struct sdtx_logger_t {
void (*func)(
const char* tag, // always "sdtx"
uint32_t log_level, // 0=panic, 1=error, 2=warning, 3=info
uint32_t log_item_id, // SDTX_LOGITEM_*
const char* message_or_null, // a message string, may be nullptr in release mode
uint32_t line_nr, // line number in sokol_debugtext.h
const char* filename_or_null, // source filename, may be nullptr in release mode
void* user_data);
void* user_data;
} sdtx_logger_t;
/* a rendering context handle */
typedef struct sdtx_context { uint32_t id; } sdtx_context;
/* the default context handle */
static const sdtx_context SDTX_DEFAULT_CONTEXT = { 0x00010001 };
/*
sdtx_range is a pointer-size-pair struct used to pass memory
blobs into sokol-debugtext. When initialized from a value type
(array or struct), use the SDTX_RANGE() macro to build
an sdtx_range struct.
*/
typedef struct sdtx_range {
const void* ptr;
size_t size;
} sdtx_range;
// disabling this for every includer isn't great, but the warning is also quite pointless
#if defined(_MSC_VER)
#pragma warning(disable:4221) /* /W4 only: nonstandard extension used: 'x': cannot be initialized using address of automatic variable 'y' */
#pragma warning(disable:4204) /* VS2015: nonstandard extension used: non-constant aggregate initializer */
#endif
#if defined(__cplusplus)
#define SDTX_RANGE(x) sdtx_range{ &x, sizeof(x) }
#else
#define SDTX_RANGE(x) (sdtx_range){ &x, sizeof(x) }
#endif
/*
sdtx_font_desc_t
Describes the pixel data of a font. A font consists of up to
256 8x8 character tiles, where each character tile is described
by 8 consecutive bytes, each byte describing 8 pixels.
For instance the character 'A' could look like this (this is also
how most home computers used to describe their fonts in ROM):
bits
7 6 5 4 3 2 1 0
. . . X X . . . byte 0: 0x18
. . X X X X . . byte 1: 0x3C
. X X . . X X . byte 2: 0x66
. X X . . X X . byte 3: 0x66
. X X X X X X . byte 4: 0x7E
. X X . . X X . byte 5: 0x66
. X X . . X X . byte 6: 0x66
. . . . . . . . byte 7: 0x00
*/
#define SDTX_MAX_FONTS (8)
typedef struct sdtx_font_desc_t {
sdtx_range data; // pointer to and size of font pixel data
uint8_t first_char; // first character index in font pixel data
uint8_t last_char; // last character index in font pixel data, inclusive (default: 255)
} sdtx_font_desc_t;
/*
sdtx_context_desc_t
Describes the initialization parameters of a rendering context. Creating
additional rendering contexts is useful if you want to render in
different sokol-gfx rendering passes, or when rendering several layers
of text.
*/
typedef struct sdtx_context_desc_t {
int max_commands; // max number of draw commands, each layer transition counts as a command, default: 4096
int char_buf_size; // max number of characters rendered in one frame, default: 4096
float canvas_width; // the initial virtual canvas width, default: 640
float canvas_height; // the initial virtual canvas height, default: 400
int tab_width; // tab width in number of characters, default: 4
sg_pixel_format color_format; // color pixel format of target render pass
sg_pixel_format depth_format; // depth pixel format of target render pass
int sample_count; // MSAA sample count of target render pass
} sdtx_context_desc_t;
/*
sdtx_allocator_t
Used in sdtx_desc_t to provide custom memory-alloc and -free functions
to sokol_debugtext.h. If memory management should be overridden, both the
alloc_fn and free_fn function must be provided (e.g. it's not valid to
override one function but not the other).
*/
typedef struct sdtx_allocator_t {
void* (*alloc_fn)(size_t size, void* user_data);
void (*free_fn)(void* ptr, void* user_data);
void* user_data;
} sdtx_allocator_t;
/*
sdtx_desc_t
Describes the sokol-debugtext API initialization parameters. Passed
to the sdtx_setup() function.
NOTE: to populate the fonts item array with builtin fonts, use any
of the following functions:
sdtx_font_kc853()
sdtx_font_kc854()
sdtx_font_z1013()
sdtx_font_cpc()
sdtx_font_c64()
sdtx_font_oric()
*/
typedef struct sdtx_desc_t {
int context_pool_size; // max number of rendering contexts that can be created, default: 8
int printf_buf_size; // size of internal buffer for snprintf(), default: 4096
sdtx_font_desc_t fonts[SDTX_MAX_FONTS]; // up to 8 fonts descriptions
sdtx_context_desc_t context; // the default context creation parameters
sdtx_allocator_t allocator; // optional memory allocation overrides (default: malloc/free)
sdtx_logger_t logger; // optional log override function (default: NO LOGGING)
} sdtx_desc_t;
/* initialization/shutdown */
SOKOL_DEBUGTEXT_API_DECL void sdtx_setup(const sdtx_desc_t* desc);
SOKOL_DEBUGTEXT_API_DECL void sdtx_shutdown(void);
/* builtin font data (use to populate sdtx_desc.font[]) */
SOKOL_DEBUGTEXT_API_DECL sdtx_font_desc_t sdtx_font_kc853(void);
SOKOL_DEBUGTEXT_API_DECL sdtx_font_desc_t sdtx_font_kc854(void);
SOKOL_DEBUGTEXT_API_DECL sdtx_font_desc_t sdtx_font_z1013(void);
SOKOL_DEBUGTEXT_API_DECL sdtx_font_desc_t sdtx_font_cpc(void);
SOKOL_DEBUGTEXT_API_DECL sdtx_font_desc_t sdtx_font_c64(void);
SOKOL_DEBUGTEXT_API_DECL sdtx_font_desc_t sdtx_font_oric(void);
/* context functions */
SOKOL_DEBUGTEXT_API_DECL sdtx_context sdtx_make_context(const sdtx_context_desc_t* desc);
SOKOL_DEBUGTEXT_API_DECL void sdtx_destroy_context(sdtx_context ctx);
SOKOL_DEBUGTEXT_API_DECL void sdtx_set_context(sdtx_context ctx);
SOKOL_DEBUGTEXT_API_DECL sdtx_context sdtx_get_context(void);
SOKOL_DEBUGTEXT_API_DECL sdtx_context sdtx_default_context(void);
/* drawing functions (call inside sokol-gfx render pass) */
SOKOL_DEBUGTEXT_API_DECL void sdtx_draw(void);
SOKOL_DEBUGTEXT_API_DECL void sdtx_context_draw(sdtx_context ctx);
SOKOL_DEBUGTEXT_API_DECL void sdtx_draw_layer(int layer_id);
SOKOL_DEBUGTEXT_API_DECL void sdtx_context_draw_layer(sdtx_context ctx, int layer_id);
/* switch render layer */
SOKOL_DEBUGTEXT_API_DECL void sdtx_layer(int layer_id);
/* switch to a different font */
SOKOL_DEBUGTEXT_API_DECL void sdtx_font(int font_index);
/* set a new virtual canvas size in screen pixels */
SOKOL_DEBUGTEXT_API_DECL void sdtx_canvas(float w, float h);
/* set a new origin in character grid coordinates */
SOKOL_DEBUGTEXT_API_DECL void sdtx_origin(float x, float y);
/* cursor movement functions (relative to origin in character grid coordinates) */
SOKOL_DEBUGTEXT_API_DECL void sdtx_home(void);
SOKOL_DEBUGTEXT_API_DECL void sdtx_pos(float x, float y);
SOKOL_DEBUGTEXT_API_DECL void sdtx_pos_x(float x);
SOKOL_DEBUGTEXT_API_DECL void sdtx_pos_y(float y);
SOKOL_DEBUGTEXT_API_DECL void sdtx_move(float dx, float dy);
SOKOL_DEBUGTEXT_API_DECL void sdtx_move_x(float dx);
SOKOL_DEBUGTEXT_API_DECL void sdtx_move_y(float dy);
SOKOL_DEBUGTEXT_API_DECL void sdtx_crlf(void);
/* set the current text color */
SOKOL_DEBUGTEXT_API_DECL void sdtx_color3b(uint8_t r, uint8_t g, uint8_t b); // RGB 0..255, A=255
SOKOL_DEBUGTEXT_API_DECL void sdtx_color3f(float r, float g, float b); // RGB 0.0f..1.0f, A=1.0f
SOKOL_DEBUGTEXT_API_DECL void sdtx_color4b(uint8_t r, uint8_t g, uint8_t b, uint8_t a); // RGBA 0..255
SOKOL_DEBUGTEXT_API_DECL void sdtx_color4f(float r, float g, float b, float a); // RGBA 0.0f..1.0f
SOKOL_DEBUGTEXT_API_DECL void sdtx_color1i(uint32_t rgba); // ABGR 0xAABBGGRR
/* text rendering */
SOKOL_DEBUGTEXT_API_DECL void sdtx_putc(char c);
SOKOL_DEBUGTEXT_API_DECL void sdtx_puts(const char* str); // does NOT append newline!
SOKOL_DEBUGTEXT_API_DECL void sdtx_putr(const char* str, int len); // 'put range', also stops at zero-char
SOKOL_DEBUGTEXT_API_DECL int sdtx_printf(const char* fmt, ...) SOKOL_DEBUGTEXT_PRINTF_ATTR;
SOKOL_DEBUGTEXT_API_DECL int sdtx_vprintf(const char* fmt, va_list args);
#ifdef __cplusplus
} /* extern "C" */
/* C++ const-ref wrappers */
inline void sdtx_setup(const sdtx_desc_t& desc) { return sdtx_setup(&desc); }
inline sdtx_context sdtx_make_context(const sdtx_context_desc_t& desc) { return sdtx_make_context(&desc); }
#endif
#endif /* SOKOL_DEBUGTEXT_INCLUDED */
// ██ ███ ███ ██████ ██ ███████ ███ ███ ███████ ███ ██ ████████ █████ ████████ ██ ██████ ███ ██
// ██ ████ ████ ██ ██ ██ ██ ████ ████ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██
// ██ ██ ████ ██ ██████ ██ █████ ██ ████ ██ █████ ██ ██ ██ ██ ███████ ██ ██ ██ ██ ██ ██ ██
// ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
// ██ ██ ██ ██ ███████ ███████ ██ ██ ███████ ██ ████ ██ ██ ██ ██ ██ ██████ ██ ████
//
// >>implementation
#ifdef SOKOL_DEBUGTEXT_IMPL
#define SOKOL_DEBUGTEXT_IMPL_INCLUDED (1)
#if defined(SOKOL_MALLOC) || defined(SOKOL_CALLOC) || defined(SOKOL_FREE)
#error "SOKOL_MALLOC/CALLOC/FREE macros are no longer supported, please use sdtx_desc_t.allocator to override memory allocation functions"
#endif
#include <string.h> // memset
#include <math.h> // fmodf
#include <stdarg.h> // for vsnprintf
#include <stdlib.h> // malloc/free
#ifndef SOKOL_API_IMPL
#define SOKOL_API_IMPL
#endif
#ifndef SOKOL_DEBUG
#ifndef NDEBUG
#define SOKOL_DEBUG
#endif
#endif
#ifndef SOKOL_ASSERT
#include <assert.h>
#define SOKOL_ASSERT(c) assert(c)
#endif
#ifndef SOKOL_UNREACHABLE
#define SOKOL_UNREACHABLE SOKOL_ASSERT(false)
#endif
#ifndef _SOKOL_UNUSED
#define _SOKOL_UNUSED(x) (void)(x)
#endif
#ifndef SOKOL_VSNPRINTF
#include <stdio.h>
#define SOKOL_VSNPRINTF vsnprintf
#endif
#define _sdtx_def(val, def) (((val) == 0) ? (def) : (val))
#define _SDTX_INIT_COOKIE (0xACBAABCA)
#define _SDTX_DEFAULT_MAX_COMMANDS (4096)
#define _SDTX_DEFAULT_CONTEXT_POOL_SIZE (8)
#define _SDTX_DEFAULT_CHAR_BUF_SIZE (4096)
#define _SDTX_DEFAULT_PRINTF_BUF_SIZE (4096)
#define _SDTX_DEFAULT_CANVAS_WIDTH (640)
#define _SDTX_DEFAULT_CANVAS_HEIGHT (480)
#define _SDTX_DEFAULT_TAB_WIDTH (4)
#define _SDTX_DEFAULT_COLOR (0xFF00FFFF)
#define _SDTX_INVALID_SLOT_INDEX (0)
#define _SDTX_SLOT_SHIFT (16)
#define _SDTX_MAX_POOL_SIZE (1<<_SDTX_SLOT_SHIFT)
#define _SDTX_SLOT_MASK (_SDTX_MAX_POOL_SIZE-1)
/* embedded font data */
static const uint8_t _sdtx_font_kc853[2048] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xFF, // 00
0x00, 0x00, 0x22, 0x72, 0x22, 0x3E, 0x00, 0x00, // 01
0x00, 0x00, 0x12, 0x32, 0x7E, 0x32, 0x12, 0x00, // 02
0x7E, 0x81, 0xB9, 0xA5, 0xB9, 0xA5, 0xB9, 0x81, // 03
0x55, 0xFF, 0x55, 0xFF, 0x55, 0xFF, 0x55, 0xFF, // 04
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, // 05
0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, // 06
0x00, 0x00, 0x3C, 0x42, 0x42, 0x7E, 0x00, 0x00, // 07
0x00, 0x10, 0x30, 0x7E, 0x30, 0x10, 0x00, 0x00, // 08
0x00, 0x08, 0x0C, 0x7E, 0x0C, 0x08, 0x00, 0x00, // 09
0x00, 0x10, 0x10, 0x10, 0x7C, 0x38, 0x10, 0x00, // 0A
0x08, 0x1C, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x00, // 0B
0x38, 0x30, 0x28, 0x08, 0x08, 0x08, 0x3E, 0x00, // 0C
0x00, 0x00, 0x12, 0x32, 0x7E, 0x30, 0x10, 0x00, // 0D
0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, // 0E
0x3E, 0x7C, 0x7C, 0x3E, 0x3E, 0x7C, 0xF8, 0xF8, // 0F
0x38, 0x30, 0x28, 0x04, 0x04, 0x04, 0x04, 0x00, // 10
0x7F, 0x08, 0x1C, 0x2A, 0x08, 0x08, 0x08, 0x00, // 11
0x00, 0x08, 0x08, 0x08, 0x2A, 0x1C, 0x08, 0x7F, // 12
0x7E, 0x81, 0x9D, 0xA1, 0xB9, 0x85, 0x85, 0xB9, // 13
0x00, 0x3C, 0x42, 0x5A, 0x5A, 0x42, 0x3C, 0x00, // 14
0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11, // 15
0x00, 0x7F, 0x22, 0x72, 0x27, 0x22, 0x7F, 0x00, // 16
0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88, // 17
0x00, 0x01, 0x09, 0x0D, 0x7F, 0x0D, 0x09, 0x01, // 18
0x00, 0x90, 0xB0, 0xFE, 0xB0, 0x90, 0x00, 0x00, // 19
0x00, 0x08, 0x7C, 0x06, 0x7C, 0x08, 0x00, 0x00, // 1A
0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, // 1B
0x7E, 0x81, 0xA1, 0xA1, 0xA1, 0xA1, 0xBD, 0x81, // 1C
0x7E, 0x81, 0xB9, 0xA5, 0xB9, 0xA5, 0xA5, 0x81, // 1D
0x7E, 0x81, 0x99, 0xA1, 0xA1, 0xA1, 0x99, 0x81, // 1E
0x00, 0x10, 0x3E, 0x60, 0x3E, 0x10, 0x00, 0x00, // 1F
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 20
0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x00, // 21
0x00, 0x66, 0x66, 0xCC, 0x00, 0x00, 0x00, 0x00, // 22
0x00, 0x36, 0x7F, 0x36, 0x36, 0x7F, 0x36, 0x00, // 23
0x18, 0x3E, 0x6C, 0x3E, 0x1B, 0x1B, 0x7E, 0x18, // 24
0x00, 0x63, 0x66, 0x0C, 0x18, 0x36, 0x66, 0x00, // 25
0x18, 0x24, 0x28, 0x11, 0x2A, 0x44, 0x4A, 0x31, // 26
0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, // 27
0x00, 0x18, 0x30, 0x30, 0x30, 0x30, 0x18, 0x00, // 28
0x00, 0x18, 0x0C, 0x0C, 0x0C, 0x0C, 0x18, 0x00, // 29
0x00, 0x00, 0x24, 0x18, 0x7E, 0x18, 0x24, 0x00, // 2A
0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, // 2B
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, // 2C
0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, // 2D
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, // 2E
0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x00, 0x00, // 2F
0x00, 0x3C, 0x6E, 0x6E, 0x76, 0x76, 0x3C, 0x00, // 30
0x00, 0x1C, 0x3C, 0x0C, 0x0C, 0x0C, 0x3E, 0x00, // 31
0x00, 0x3C, 0x66, 0x06, 0x3C, 0x60, 0x7E, 0x00, // 32
0x00, 0x3C, 0x66, 0x0C, 0x06, 0x66, 0x3C, 0x00, // 33
0x00, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x0C, 0x00, // 34
0x00, 0x7E, 0x60, 0x7C, 0x06, 0x66, 0x3C, 0x00, // 35
0x00, 0x3C, 0x60, 0x7C, 0x66, 0x66, 0x3C, 0x00, // 36
0x00, 0x7E, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, // 37
0x00, 0x3C, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0x00, // 38
0x00, 0x3C, 0x66, 0x66, 0x3E, 0x06, 0x3C, 0x00, // 39
0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, // 3A
0x00, 0x00, 0x18, 0x00, 0x18, 0x18, 0x30, 0x00, // 3B
0x00, 0x00, 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, // 3C
0x00, 0x00, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x00, // 3D
0x00, 0x00, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x00, // 3E
0x00, 0x3C, 0x66, 0x06, 0x1C, 0x18, 0x00, 0x18, // 3F
0x3C, 0x42, 0x81, 0x35, 0x49, 0x49, 0x49, 0x36, // 40
0x00, 0x3C, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x00, // 41
0x00, 0x7C, 0x66, 0x7C, 0x66, 0x66, 0x7C, 0x00, // 42
0x00, 0x3C, 0x66, 0x60, 0x60, 0x66, 0x3C, 0x00, // 43
0x00, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x00, // 44
0x00, 0x7E, 0x60, 0x7C, 0x60, 0x60, 0x7E, 0x00, // 45
0x00, 0x7E, 0x60, 0x7C, 0x60, 0x60, 0x60, 0x00, // 46
0x00, 0x3C, 0x66, 0x60, 0x6E, 0x66, 0x3C, 0x00, // 47
0x00, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, // 48
0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, // 49
0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x6C, 0x38, 0x00, // 4A
0x00, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0x63, 0x00, // 4B
0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7E, 0x00, // 4C
0x00, 0x63, 0x77, 0x6B, 0x63, 0x63, 0x63, 0x00, // 4D
0x00, 0x63, 0x73, 0x6B, 0x67, 0x63, 0x63, 0x00, // 4E
0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, // 4F
0x00, 0x7C, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x00, // 50
0x00, 0x3C, 0x66, 0x66, 0x6E, 0x66, 0x3A, 0x01, // 51
0x00, 0x7C, 0x66, 0x7C, 0x6C, 0x66, 0x63, 0x00, // 52
0x00, 0x3C, 0x60, 0x3C, 0x06, 0x66, 0x3C, 0x00, // 53
0x00, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, // 54
0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, // 55
0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, // 56
0x00, 0x63, 0x63, 0x6B, 0x6B, 0x7F, 0x36, 0x00, // 57
0x00, 0x66, 0x3C, 0x18, 0x18, 0x3C, 0x66, 0x00, // 58
0x00, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x00, // 59
0x00, 0x7E, 0x0C, 0x18, 0x30, 0x60, 0x7E, 0x00, // 5A
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 5B
0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, // 5C
0x00, 0x7E, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, // 5D
0x00, 0x00, 0x00, 0x08, 0x1C, 0x36, 0x00, 0x00, // 5E
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, // 5F
0x7E, 0x81, 0x99, 0xA1, 0xA1, 0x99, 0x81, 0x7E, // 60
0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3B, 0x00, // 61
0x00, 0x60, 0x60, 0x78, 0x6C, 0x6C, 0x78, 0x00, // 62
0x00, 0x00, 0x3C, 0x66, 0x60, 0x66, 0x3C, 0x00, // 63
0x00, 0x06, 0x06, 0x1E, 0x36, 0x36, 0x1E, 0x00, // 64
0x00, 0x00, 0x38, 0x6C, 0x7C, 0x60, 0x38, 0x00, // 65
0x00, 0x1E, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x00, // 66
0x00, 0x00, 0x3C, 0x66, 0x66, 0x3F, 0x06, 0x3C, // 67
0x00, 0x60, 0x60, 0x6C, 0x76, 0x66, 0x66, 0x00, // 68
0x00, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, // 69
0x00, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x30, // 6A
0x00, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0x00, // 6B
0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x00, // 6C
0x00, 0x00, 0x36, 0x7F, 0x6B, 0x63, 0x63, 0x00, // 6D
0x00, 0x00, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x00, // 6E
0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00, // 6F
0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60, // 70
0x00, 0x00, 0x3C, 0x66, 0x66, 0x3E, 0x06, 0x06, // 71
0x00, 0x00, 0x36, 0x38, 0x30, 0x30, 0x30, 0x00, // 72
0x00, 0x00, 0x1C, 0x30, 0x1C, 0x06, 0x3C, 0x00, // 73
0x00, 0x18, 0x18, 0x3C, 0x18, 0x18, 0x0C, 0x00, // 74
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, // 75
0x00, 0x00, 0x66, 0x66, 0x3C, 0x3C, 0x18, 0x00, // 76
0x00, 0x00, 0x63, 0x63, 0x6B, 0x7F, 0x36, 0x00, // 77
0x00, 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x00, // 78
0x00, 0x00, 0x66, 0x3C, 0x18, 0x30, 0x60, 0x00, // 79
0x00, 0x00, 0x7E, 0x0C, 0x18, 0x30, 0x7E, 0x00, // 7A
0x66, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3B, 0x00, // 7B
0x66, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00, // 7C
0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, // 7D
0x00, 0x38, 0x6C, 0x78, 0x6C, 0x78, 0x60, 0x60, // 7E
0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, // 7F
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x00, // 80
0xFF, 0xFF, 0xDD, 0x8D, 0xDD, 0xC1, 0xFF, 0xFF, // 81
0xFF, 0xFF, 0xED, 0xCD, 0x81, 0xCD, 0xED, 0xFF, // 82
0x81, 0x7E, 0x46, 0x5A, 0x46, 0x5A, 0x46, 0x7E, // 83
0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, // 84
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, // 85
0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, // 86
0xFF, 0xFF, 0xC3, 0xBD, 0xBD, 0x81, 0xFF, 0xFF, // 87
0xFF, 0xEF, 0xCF, 0x81, 0xCF, 0xEF, 0xFF, 0xFF, // 88
0xFF, 0xF7, 0xF3, 0x81, 0xF3, 0xF7, 0xFF, 0xFF, // 89
0xFF, 0xEF, 0xEF, 0xEF, 0x83, 0xC7, 0xEF, 0xFF, // 8A
0xF7, 0xE3, 0xC1, 0xF7, 0xF7, 0xF7, 0xF7, 0xFF, // 8B
0xC7, 0xCF, 0xD7, 0xF7, 0xF7, 0xF7, 0xC1, 0xFF, // 8C
0xFF, 0xFF, 0xED, 0xCD, 0x81, 0xCF, 0xEF, 0xFF, // 8D
0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, // 8E
0xC1, 0x83, 0x83, 0xC1, 0xC1, 0x83, 0x07, 0x07, // 8F
0xC7, 0xCF, 0xD7, 0xFB, 0xFB, 0xFB, 0xFB, 0xFF, // 90
0x80, 0xF7, 0xE3, 0xD5, 0xF7, 0xF7, 0xF7, 0xFF, // 91
0xFF, 0xF7, 0xF7, 0xF7, 0xD5, 0xE3, 0xF7, 0x80, // 92
0x81, 0x7E, 0x62, 0x5E, 0x46, 0x7A, 0x7A, 0x46, // 93
0xFF, 0xC3, 0xBD, 0xA5, 0xA5, 0xBD, 0xC3, 0xFF, // 94
0x77, 0xBB, 0xDD, 0xEE, 0x77, 0xBB, 0xDD, 0xEE, // 95
0xFF, 0x80, 0xDD, 0x8D, 0xD8, 0xDD, 0x80, 0xFF, // 96
0xEE, 0xDD, 0xBB, 0x77, 0xEE, 0xDD, 0xBB, 0x77, // 97
0xFF, 0xFE, 0xF6, 0xF2, 0x80, 0xF2, 0xF6, 0xFE, // 98
0xFF, 0x6F, 0x4F, 0x01, 0x4F, 0x6F, 0xFF, 0xFF, // 99
0xFF, 0xF7, 0x83, 0xF9, 0x83, 0xF7, 0xFF, 0xFF, // 9A
0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, // 9B
0x81, 0x7E, 0x5E, 0x5E, 0x5E, 0x5E, 0x42, 0x7E, // 9C
0x81, 0x7E, 0x46, 0x5A, 0x46, 0x5A, 0x5A, 0x7E, // 9D
0x81, 0x7E, 0x66, 0x5E, 0x5E, 0x5E, 0x66, 0x7E, // 9E
0xFF, 0xEF, 0xC1, 0x9F, 0xC1, 0xEF, 0xFF, 0xFF, // 9F
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // A0
0xFF, 0xE7, 0xE7, 0xE7, 0xE7, 0xFF, 0xE7, 0xFF, // A1
0xFF, 0x99, 0x99, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, // A2
0xFF, 0xC9, 0x80, 0xC9, 0xC9, 0x80, 0xC9, 0xFF, // A3
0xE7, 0xC1, 0x93, 0xC1, 0xE4, 0xE4, 0x81, 0xE7, // A4
0xFF, 0x9C, 0x99, 0xF3, 0xE7, 0xC9, 0x99, 0xFF, // A5
0xE7, 0xDB, 0xD7, 0xEE, 0xD5, 0xBB, 0xB5, 0xCE, // A6
0xFF, 0xE7, 0xE7, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, // A7
0xFF, 0xE7, 0xCF, 0xCF, 0xCF, 0xCF, 0xE7, 0xFF, // A8
0xFF, 0xE7, 0xF3, 0xF3, 0xF3, 0xF3, 0xE7, 0xFF, // A9
0xFF, 0xFF, 0xDB, 0xE7, 0x81, 0xE7, 0xDB, 0xFF, // AA
0xFF, 0xFF, 0xE7, 0xE7, 0x81, 0xE7, 0xE7, 0xFF, // AB
0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xE7, 0xCF, 0xFF, // AC
0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, // AD
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xE7, 0xFF, // AE