Skip to content

Instantly share code, notes, and snippets.

@death
Last active June 17, 2021 23:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save death/89156262b6b3e25abc3b52da18c2ba24 to your computer and use it in GitHub Desktop.
Save death/89156262b6b3e25abc3b52da18c2ba24 to your computer and use it in GitHub Desktop.
simple graphics
modified src/autowrap.lisp
@@ -9,7 +9,8 @@
"/usr/include/"
"/usr/include/arm-linux-gnueabihf"
"/usr/include/X11/")
- :include-sources ("SDL2_gfxPrimitives.h")
+ :include-sources ("SDL2_gfxPrimitives.h"
+ "SDL2_framerate.h")
:exclude-definitions ("SDL_LogMessageV"
"SDL_vsnprintf"
"_inline$"
(defpackage #:snippets/simple-graphics-data
(:use #:cl)
(:export
#:*10x20-font*
#:*vga-palette*))
(in-package #:snippets/simple-graphics-data)
;; Font taken from lispbuilder-sdl.
(defvar *10x20-font*
#(0 0 0 0 0 0 115 128 64 128 64 128 0 0 0 0 64 128 64 128 64 128 0 0 0 0 64 128
64 128 115 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 30 0 63 0 127 128
127 128 63 0 30 0 12 0 0 0 0 0 0 0 0 0 0 0 0 0 85 64 170 128 85 64 170 128 85
64 170 128 85 64 170 128 85 64 170 128 85 64 170 128 85 64 170 128 85 64 170
128 85 64 170 128 85 64 170 128 0 0 0 0 102 0 102 0 102 0 126 0 102 0 102 0
102 0 0 0 31 128 6 0 6 0 6 0 6 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 124 0 96 0 96 0
120 0 96 0 96 0 96 0 15 128 12 0 12 0 15 0 12 0 12 0 12 0 0 0 0 0 0 0 0 0 0 0
0 0 60 0 102 0 96 0 96 0 102 0 60 0 0 0 31 0 25 128 25 128 31 0 30 0 27 0 25
128 0 0 0 0 0 0 0 0 0 0 0 0 48 0 48 0 48 0 48 0 48 0 62 0 0 0 15 128 12 0 12 0
15 0 12 0 12 0 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 30 0 51 0 51 0 30 0 12 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0
12 0 127 128 12 0 12 0 0 0 127 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 102 0 118 0
126 0 126 0 110 0 102 0 0 0 12 0 12 0 12 0 12 0 12 0 12 0 15 128 0 0 0 0 0 0 0
0 0 0 0 0 102 0 102 0 102 0 60 0 60 0 24 0 24 0 0 0 31 128 6 0 6 0 6 0 6 0 6 0
0 0 0 0 0 0 0 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 248 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 248 0 8 0 8 0 8 0 8 0
8 0 8 0 8 0 8 0 8 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 192 8 0 8 0 8 0
8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 15 192 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 255 192 8
0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 255 192 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 192 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 255 192 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 192 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 192 8 0 8 0 8
0 8 0 8 0 8 0 8 0 8 0 8 0 15 192 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8
0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 248 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8
0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 255 192 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 192 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8
0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0 8 0
8 0 8 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 3 128 14 0 56 0 224 0 56 0 14 0 3 128 0 0
0 0 255 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 224 0 56 0 14 0 3 128 14 0
56 0 224 0 0 0 0 0 255 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127
128 51 0 51 0 51 0 51 0 51 0 51 0 51 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 0 3 0 6 0 127 128 12 0 12 0 127 128 24 0 48 0 48 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 15 0 25 128 25 128 24 0 24 0 126 0 24 0 24 0 24 0 124 0 86 192 115 128 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 0 14 0 14 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0
12 0 0 0 12 0 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 51 0 51 0 51 0 18 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 128 13 128 13 128
63 192 27 0 27 0 27 0 127 128 54 0 54 0 54 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
12 0 63 0 109 128 108 0 108 0 108 0 63 0 13 128 13 128 13 128 109 128 63 0 12
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 57 128 109 128 111 0 59 0 6 0 6 0 12 0 12 0
27 128 30 192 54 192 51 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 0 54 0 54 0 54 0 60
0 24 0 56 0 108 0 102 192 99 128 99 0 119 128 60 192 0 0 0 0 0 0 0 0 0 0 0 0 0
0 12 0 12 0 12 0 12 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 3 0 6 0 12 0 12 0 24 0 24 0 24 0 24 0 24 0 12 0 12 0 6 0 3 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 48 0 24 0 12 0 12 0 6 0 6 0 6 0 6 0 6 0 12 0 12 0 24 0 48 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 51 0 51 0 30 0 127 128 30 0 51 0 51 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 12 0 12 0 127 128 12
0 12 0 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 14 0 14 0 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 127 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 14 0 14 0 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 128 1
128 3 0 3 0 6 0 6 0 12 0 12 0 24 0 24 0 48 0 48 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
12 0 30 0 51 0 51 0 97 128 97 128 97 128 97 128 97 128 51 0 51 0 30 0 12 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 12 0 28 0 60 0 108 0 12 0 12 0 12 0 12 0 12 0 12 0 12
0 12 0 127 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 30 0 51 0 97 128 97 128 1 128 1 128
3 0 14 0 24 0 48 0 96 0 96 0 127 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 30 0 51 0 97
128 97 128 1 128 3 0 14 0 3 0 1 128 97 128 97 128 51 0 30 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 3 0 7 0 15 0 27 0 51 0 99 0 99 0 127 128 3 0 3 0 3 0 3 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 127 128 96 0 96 0 96 0 96 0 110 0 115 0 1 128 1 128 1 128
97 128 51 0 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 30 0 51 0 97 0 96 0 96 0 110 0
115 0 97 128 97 128 97 128 97 128 51 0 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127
128 1 128 1 128 3 0 3 0 6 0 6 0 12 0 12 0 24 0 24 0 48 0 48 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 30 0 51 0 97 128 97 128 97 128 51 0 30 0 51 0 97 128 97 128 97 128
51 0 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 30 0 51 0 97 128 97 128 97 128 97 128 51
128 29 128 1 128 1 128 33 128 51 0 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 14 0 14 0 0 0 0 0 0 0 0 0 14 0 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 14 0 14 0 0 0 0 0 0 0 0 0 14 0 14 0 28 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 3 0 6 0 12 0 24 0 48 0 96 0 48 0 24 0 12 0 6 0 3 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 127 128 0 0 0 0 0 0 0 0 127 128 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 32 0 48 0 24 0 12 0 6 0 3 0 1 128 3 0 6 0 12 0 24 0 48 0
32 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 30 0 51 0 97 128 97 128 97 128 3 0 6 0 12 0
12 0 12 0 0 0 12 0 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 30 0 51 0 97 128 103 128
111 128 109 128 109 128 109 128 111 0 102 0 96 0 49 128 31 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 12 0 30 0 51 0 51 0 97 128 97 128 97 128 127 128 97 128 97 128 97
128 97 128 97 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 124 0 102 0 99 0 99 0 99 0 102 0
126 0 99 0 97 128 97 128 97 128 99 0 126 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 30 0 51
0 97 128 96 0 96 0 96 0 96 0 96 0 96 0 96 0 97 128 51 0 30 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 126 0 99 0 97 128 97 128 97 128 97 128 97 128 97 128 97 128 97 128
97 128 99 0 126 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 128 96 0 96 0 96 0 96 0 96 0
126 0 96 0 96 0 96 0 96 0 96 0 127 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 128 96
0 96 0 96 0 96 0 96 0 126 0 96 0 96 0 96 0 96 0 96 0 96 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 30 0 51 0 97 128 96 0 96 0 96 0 103 128 97 128 97 128 97 128 97 128 51
128 30 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 97 128 97 128 97 128 97 128 97 128 97
128 127 128 97 128 97 128 97 128 97 128 97 128 97 128 0 0 0 0 0 0 0 0 0 0 0 0
0 0 127 128 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 127 128 0 0
0 0 0 0 0 0 0 0 0 0 0 0 15 192 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 99 0 99 0 54 0
28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 97 128 97 128 99 0 99 0 102 0 102 0 124 0 102
0 102 0 99 0 99 0 97 128 97 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 96 0 96 0 96 0 96
0 96 0 96 0 96 0 96 0 96 0 96 0 96 0 96 0 127 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0
97 128 97 128 115 128 115 128 127 128 109 128 109 128 109 128 109 128 97 128
97 128 97 128 97 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 97 128 113 128 113 128 121
128 121 128 109 128 109 128 103 128 103 128 99 128 99 128 97 128 97 128 0 0 0
0 0 0 0 0 0 0 0 0 0 0 30 0 51 0 97 128 97 128 97 128 97 128 97 128 97 128 97
128 97 128 97 128 51 0 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 126 0 99 0 97 128 97
128 97 128 97 128 99 0 126 0 96 0 96 0 96 0 96 0 96 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 30 0 51 0 97 128 97 128 97 128 97 128 97 128 97 128 97 128 109 128 103 128
51 0 31 0 1 128 0 0 0 0 0 0 0 0 0 0 0 0 126 0 99 0 97 128 97 128 97 128 97 128
99 0 126 0 102 0 99 0 99 0 97 128 97 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 30 0 51 0
97 128 96 0 96 0 48 0 30 0 3 0 1 128 1 128 97 128 51 0 30 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 127 128 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 97 128 97 128 97 128 97 128 97 128 97 128 97 128
97 128 97 128 97 128 97 128 51 0 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 97 128 97
128 97 128 97 128 51 0 51 0 51 0 30 0 30 0 30 0 12 0 12 0 12 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 97 128 97 128 97 128 97 128 97 128 109 128 109 128 109 128 109 128
115 128 115 128 97 128 97 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 97 128 97 128 51 0
51 0 30 0 30 0 12 0 30 0 30 0 51 0 51 0 97 128 97 128 0 0 0 0 0 0 0 0 0 0 0 0
0 0 97 128 97 128 51 0 51 0 30 0 30 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 127 128 1 128 1 128 3 0 6 0 6 0 12 0 24 0 24 0 48 0 96 0
96 0 127 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 63 0 48 0 48 0 48 0 48 0 48 0 48 0 48
0 48 0 48 0 48 0 48 0 63 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 48 0 48 0 24 0 24 0
12 0 12 0 6 0 6 0 3 0 3 0 1 128 1 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 63 0 3 0 3 0
3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 63 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 30 0
51 0 97 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 192 0 0 0 0 0 0 0 0 0 0
0 0 24 0 12 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 31 0 49 128 1 128 63 128 97 128 97 128 97 128 62
128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 96 0 96 0 96 0 96 0 96 0 110 0 115 0 97 128 97
128 97 128 97 128 115 0 110 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
31 0 49 128 96 0 96 0 96 0 96 0 49 128 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 128
1 128 1 128 1 128 1 128 29 128 51 128 97 128 97 128 97 128 97 128 51 128 29
128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 30 0 51 0 97 128 127 128
96 0 96 0 49 128 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 0 25 128 25 128 24 0 24 0
126 0 24 0 24 0 24 0 24 0 24 0 24 0 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 62 128 99 128 99 0 99 0 99 0 62 0 96 0 63 0 97 128 97 128 97 128 63
0 0 0 0 0 0 0 96 0 96 0 96 0 96 0 96 0 110 0 115 0 97 128 97 128 97 128 97 128
97 128 97 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 12 0 0 0 60 0 12 0 12 0
12 0 12 0 12 0 12 0 127 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 128 1 128 0
0 7 128 1 128 1 128 1 128 1 128 1 128 1 128 1 128 49 128 49 128 49 128 31 0 0
0 0 0 0 0 96 0 96 0 96 0 96 0 96 0 99 0 102 0 108 0 120 0 124 0 102 0 99 0 97
128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 60 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0
12 0 12 0 12 0 127 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 91 0
127 128 109 128 109 128 109 128 109 128 109 128 109 128 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 110 0 115 0 97 128 97 128 97 128 97 128 97 128 97
128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 30 0 51 0 97 128 97 128 97
128 97 128 51 0 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 110 0 115
0 97 128 97 128 97 128 97 128 115 0 110 0 96 0 96 0 96 0 96 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 29 128 51 128 97 128 97 128 97 128 97 128 51 128 29 128 1 128
1 128 1 128 1 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 111 0 57 128 48 0 48 0 48 0
48 0 48 0 48 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 63 0 97 128 96
0 63 0 1 128 1 128 97 128 63 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 0 24 0
24 0 126 0 24 0 24 0 24 0 24 0 24 0 25 128 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 97 128 97 128 97 128 97 128 97 128 97 128 51 128 29 128 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 97 128 97 128 51 0 51 0 30 0 30 0
12 0 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 97 128 97 128 97 128
109 128 109 128 109 128 127 128 51 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 97 128 51 0 30 0 12 0 12 0 30 0 51 0 97 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 97 128 97 128 97 128 97 128 97 128 97 128 51 128 29 128 1
128 97 128 51 0 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 63 128 1 128 3 0 6 0 12 0
24 0 48 0 63 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 128 12 0 12 0 12 0 12 0 12 0
120 0 12 0 12 0 12 0 12 0 12 0 7 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 12 0 12
0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 120 0 12 0 12 0 12 0 12 0 12 0 7 128 12 0 12 0 12 0 12 0 12 0 120 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 57 128 109 128 103 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 12 0 12 0 0 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0
12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 12 0 30 0 51 0 97 0 96 0 96 0 97 0
51 0 30 0 12 0 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 0 25 128 25 128 24 0 24
0 126 0 24 0 24 0 24 0 124 0 86 192 115 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 128 128 221 128 127 0 99 0 99 0 99 0 127 0 221 128 128 128 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 64 128 97 128 51 0 30 0 63 0 12 0 63 0 12 0 12 0 12
0 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 12 0 12 0 12 0 12 0 0 0 0 0 0 0 12 0
12 0 12 0 12 0 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 30 0 51 0 99 0 48 0 60 0 102 0
51 0 25 128 15 0 3 0 49 128 51 0 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 51 0 51 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
30 0 51 0 97 128 94 128 82 128 80 128 82 128 94 128 97 128 51 0 30 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 31 0 33 128 1 128 63 128 97 128 97 128 62 128 0 0 127 128 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 128 13 128 27 0 54 0 108 0
216 0 108 0 54 0 27 0 13 128 4 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 127 128 127 128 1 128 1 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 63 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 30 0 51 0 97 128 94 128 82 128 94 128 84 128 86 128 97 128 51 0 30 0 0
0 0 0 0 0 0 0 0 0 0 0 127 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 30 0 51 0 51 0 30 0 12 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 12 0 127 128 12 0
12 0 0 0 127 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 0 54 0 6 0 12 0 24 0
48 0 62 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 0 54 0 6 0 12
0 6 0 54 0 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 0 12 0
24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 99 0 99 0 99 0 99 0 99 0 119 0 125 0 96 0 96 0 96 0 0 0 0 0
0 0 0 0 63 128 127 128 125 128 125 128 125 128 61 128 13 128 13 128 13 128 13
128 13 128 13 128 13 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 0
14 0 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 6 0 54 0 28 0 0 0 0 0 0 0 24 0 56 0 24 0
24 0 24 0 24 0 60 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 0
54 0 99 0 99 0 99 0 54 0 28 0 0 0 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 72 0 108 0 54 0 27 0 13 128 6 192 13 128 27 0 54 0 108 0 72 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 32 0 96 0 32 128 33 0 114 0 4 0 9 0 19 0 37 0 79 0 1
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32 0 96 0 32 128 33 0 114 0 4 0 11 0 20
128 32 128 65 0 2 0 7 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 112 0 8 0 48 128 9 0
114 0 4 0 9 0 19 0 37 0 79 128 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 12
0 0 0 12 0 12 0 12 0 24 0 48 0 97 128 97 128 97 128 51 0 30 0 0 0 0 0 0 0 0 0
0 0 48 0 24 0 12 0 0 0 12 0 30 0 51 0 97 128 97 128 97 128 127 128 97 128 97
128 97 128 97 128 0 0 0 0 0 0 0 0 0 0 3 0 6 0 12 0 0 0 12 0 30 0 51 0 97 128
97 128 97 128 127 128 97 128 97 128 97 128 97 128 0 0 0 0 0 0 0 0 0 0 12 0 30
0 51 0 0 0 12 0 30 0 51 0 97 128 97 128 97 128 127 128 97 128 97 128 97 128 97
128 0 0 0 0 0 0 0 0 0 0 25 0 63 0 38 0 0 0 12 0 30 0 51 0 97 128 97 128 97 128
127 128 97 128 97 128 97 128 97 128 0 0 0 0 0 0 0 0 0 0 51 0 51 0 0 0 12 0 30
0 51 0 51 0 97 128 97 128 97 128 127 128 97 128 97 128 97 128 97 128 0 0 0 0 0
0 0 0 30 0 51 0 51 0 30 0 0 0 12 0 30 0 51 0 97 128 97 128 97 128 127 128 97
128 97 128 97 128 97 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 128 30 0 54 0 54 0 102
0 102 0 127 128 102 0 102 0 102 0 102 0 102 0 103 128 0 0 0 0 0 0 0 0 0 0 0 0
0 0 30 0 51 0 97 128 96 0 96 0 96 0 96 0 96 0 96 0 96 0 97 128 51 0 30 0 12 0
6 0 54 0 28 0 0 0 48 0 24 0 12 0 0 0 127 128 96 0 96 0 96 0 96 0 126 0 96 0 96
0 96 0 96 0 127 128 0 0 0 0 0 0 0 0 0 0 6 0 12 0 24 0 0 0 127 128 96 0 96 0 96
0 96 0 126 0 96 0 96 0 96 0 96 0 127 128 0 0 0 0 0 0 0 0 0 0 12 0 30 0 51 0 0
0 127 128 96 0 96 0 96 0 96 0 126 0 96 0 96 0 96 0 96 0 127 128 0 0 0 0 0 0 0
0 0 0 51 0 51 0 0 0 0 0 127 128 96 0 96 0 96 0 96 0 126 0 96 0 96 0 96 0 96 0
127 128 0 0 0 0 0 0 0 0 0 0 24 0 12 0 6 0 0 0 63 0 12 0 12 0 12 0 12 0 12 0 12
0 12 0 12 0 12 0 63 0 0 0 0 0 0 0 0 0 0 0 6 0 12 0 24 0 0 0 63 0 12 0 12 0 12
0 12 0 12 0 12 0 12 0 12 0 12 0 63 0 0 0 0 0 0 0 0 0 0 0 12 0 30 0 51 0 0 0 63
0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 63 0 0 0 0 0 0 0 0 0 0 0 51 0
51 0 0 0 63 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 12 0 63 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 126 0 99 0 97 128 97 128 97 128 97 128 249 128 97 128 97 128
97 128 97 128 99 0 126 0 0 0 0 0 0 0 0 0 0 0 25 0 63 0 38 0 0 0 97 128 113 128
121 128 121 128 109 128 109 128 103 128 103 128 99 128 97 128 97 128 0 0 0 0 0
0 0 0 0 0 24 0 12 0 6 0 0 0 30 0 51 0 97 128 97 128 97 128 97 128 97 128 97
128 97 128 51 0 30 0 0 0 0 0 0 0 0 0 0 0 6 0 12 0 24 0 0 0 30 0 51 0 97 128 97
128 97 128 97 128 97 128 97 128 97 128 51 0 30 0 0 0 0 0 0 0 0 0 0 0 12 0 30 0
51 0 0 0 30 0 51 0 97 128 97 128 97 128 97 128 97 128 97 128 97 128 51 0 30 0
0 0 0 0 0 0 0 0 0 0 25 0 63 0 38 0 0 0 30 0 51 0 97 128 97 128 97 128 97 128
97 128 97 128 97 128 51 0 30 0 0 0 0 0 0 0 0 0 0 0 51 0 51 0 0 0 30 0 51 0 97
128 97 128 97 128 97 128 97 128 97 128 97 128 97 128 51 0 30 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 65 0 99 0 54 0 28 0 28 0 54 0 99 0 65 0 0 0 0
0 0 0 0 0 0 0 0 0 0 128 31 0 51 0 99 128 99 128 101 128 101 128 101 128 105
128 105 128 105 128 113 128 51 0 62 0 64 0 0 0 0 0 0 0 0 0 24 0 12 0 6 0 0 0
97 128 97 128 97 128 97 128 97 128 97 128 97 128 97 128 97 128 51 0 30 0 0 0 0
0 0 0 0 0 0 0 6 0 12 0 24 0 0 0 97 128 97 128 97 128 97 128 97 128 97 128 97
128 97 128 97 128 51 0 30 0 0 0 0 0 0 0 0 0 0 0 12 0 30 0 51 0 0 0 97 128 97
128 97 128 97 128 97 128 97 128 97 128 97 128 97 128 51 0 30 0 0 0 0 0 0 0 0 0
0 0 51 0 51 0 0 0 97 128 97 128 97 128 97 128 97 128 97 128 97 128 97 128 97
128 97 128 51 0 30 0 0 0 0 0 0 0 0 0 0 0 6 0 12 0 24 0 0 0 97 128 97 128 51 0
51 0 30 0 30 0 12 0 12 0 12 0 12 0 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 48 0 48 0
48 0 63 0 49 128 49 128 49 128 49 128 49 128 63 0 48 0 48 0 48 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 14 0 27 0 49 128 49 128 51 0 118 0 54 0 51 0 49 128 49 128 49
128 51 0 54 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 0 12 0 6 0 0 0 63 0 97 128 1
128 63 128 97 128 97 128 97 128 62 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 0 12
0 24 0 0 0 63 0 97 128 1 128 63 128 97 128 97 128 97 128 62 128 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 12 0 30 0 51 0 0 0 63 0 97 128 1 128 63 128 97 128 97 128 97
128 62 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 25 0 63 0 38 0 0 0 63 0 97 128 1
128 63 128 97 128 97 128 97 128 62 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 51
0 51 0 0 0 63 0 97 128 1 128 63 128 97 128 97 128 97 128 62 128 0 0 0 0 0 0 0
0 0 0 0 0 0 0 30 0 51 0 51 0 30 0 0 0 63 0 97 128 1 128 63 128 97 128 97 128
97 128 62 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 59 0 77 128 13
128 15 0 60 0 108 0 108 128 55 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 31 0 49 128 96 0 96 0 96 0 96 0 49 128 31 0 12 0 6 0 54 0 28 0 0 0 0 0 0 0 0
0 48 0 24 0 12 0 0 0 30 0 51 0 97 128 127 128 96 0 96 0 49 128 31 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 3 0 6 0 12 0 0 0 30 0 51 0 97 128 127 128 96 0 96 0 49
128 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 30 0 51 0 0 0 30 0 51 0 97 128
127 128 96 0 96 0 49 128 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 51 0 51 0 0
0 30 0 51 0 97 128 127 128 96 0 96 0 49 128 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 48 0 24 0 12 0 0 0 60 0 12 0 12 0 12 0 12 0 12 0 12 0 127 128 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 6 0 12 0 24 0 0 0 60 0 12 0 12 0 12 0 12 0 12 0 12 0 127 128
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 30 0 51 0 0 0 60 0 12 0 12 0 12 0 12 0 12
0 12 0 127 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 51 0 51 0 0 0 60 0 12 0 12
0 12 0 12 0 12 0 12 0 127 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 68 0 108 0 56 0 56 0
108 0 70 0 31 0 51 128 97 128 97 128 97 128 51 0 30 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 25 0 63 0 38 0 0 0 110 0 115 0 97 128 97 128 97 128 97 128 97 128 97
128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 48 0 24 0 12 0 0 0 30 0 51 0 97 128 97 128
97 128 97 128 51 0 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 6 0 12 0 0 0 30 0
51 0 97 128 97 128 97 128 97 128 51 0 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12
0 30 0 51 0 0 0 30 0 51 0 97 128 97 128 97 128 97 128 51 0 30 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 25 0 63 0 38 0 0 0 30 0 51 0 97 128 97 128 97 128 97 128 51
0 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 51 0 51 0 0 0 30 0 51 0 97 128 97
128 97 128 97 128 51 0 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 12 0 0 0
0 0 127 128 127 128 0 0 0 0 12 0 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 128 31 0 51 0 101 128 101 128 105 128 105 128 51 0 62 0 64 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 24 0 12 0 6 0 0 0 97 128 97 128 97 128 97 128 97 128 97
128 51 128 29 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 6 0 12 0 0 0 97 128 97
128 97 128 97 128 97 128 97 128 51 128 29 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
12 0 30 0 51 0 0 0 97 128 97 128 97 128 97 128 97 128 97 128 51 128 29 128 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 51 0 51 0 0 0 97 128 97 128 97 128 97 128 97
128 97 128 51 128 29 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 0 12 0 24 0 0 0 97
128 97 128 97 128 97 128 97 128 97 128 51 128 29 128 1 128 97 128 51 0 30 0 0
0 0 0 0 0 48 0 48 0 48 0 48 0 48 0 48 0 62 0 51 0 49 128 49 128 49 128 51 0 62
0 48 0 48 0 48 0 48 0 0 0 0 0 0 0 0 0 0 0 51 0 51 0 0 0 97 128 97 128 97 128
97 128 97 128 97 128 51 128 29 128 1 128 97 128 51 0 30 0))
(defvar *vga-palette*
(let ((*read-base* 16))
(read-from-string
"((00 00 00) (00 00 AA) (00 AA 00) (00 AA AA) (AA 00 00) (AA 00 AA) (AA 55 00) (AA AA AA)
(55 55 55) (55 55 FF) (55 FF 55) (55 FF FF) (FF 55 55) (FF 55 FF) (FF FF 55) (FF FF FF)
(00 00 00) (10 10 10) (20 20 20) (35 35 35) (45 45 45) (55 55 55) (65 65 65) (75 75 75)
(8A 8A 8A) (9A 9A 9A) (AA AA AA) (BA BA BA) (CA CA CA) (DF DF DF) (EF EF EF) (FF FF FF)
(00 00 FF) (41 00 FF) (82 00 FF) (BE 00 FF) (FF 00 FF) (FF 00 BE) (FF 00 82) (FF 00 41)
(FF 00 00) (FF 41 00) (FF 82 00) (FF BE 00) (FF FF 00) (BE FF 00) (82 FF 00) (41 FF 00)
(00 FF 00) (00 FF 41) (00 FF 82) (00 FF BE) (00 FF FF) (00 BE FF) (00 82 FF) (00 41 FF)
(82 82 FF) (9E 82 FF) (BE 82 FF) (DF 82 FF) (FF 82 FF) (FF 82 DF) (FF 82 BE) (FF 82 9E)
(FF 82 82) (FF 9E 82) (FF BE 82) (FF DF 82) (FF FF 82) (DF FF 82) (BE FF 82) (9E FF 82)
(82 FF 82) (82 FF 9E) (82 FF BE) (82 FF DF) (82 FF FF) (82 DF FF) (82 BE FF) (82 9E FF)
(BA BA FF) (CA BA FF) (DF BA FF) (EF BA FF) (FF BA FF) (FF BA EF) (FF BA DF) (FF BA CA)
(FF BA BA) (FF CA BA) (FF DF BA) (FF EF BA) (FF FF BA) (EF FF BA) (DF FF BA) (CA FF BA)
(BA FF BA) (BA FF CA) (BA FF DF) (BA FF EF) (BA FF FF) (BA EF FF) (BA DF FF) (BA CA FF)
(00 00 71) (1C 00 71) (39 00 71) (55 00 71) (71 00 71) (71 00 55) (71 00 39) (71 00 1C)
(71 00 00) (71 1C 00) (71 39 00) (71 55 00) (71 71 00) (55 71 00) (39 71 00) (1C 71 00)
(00 71 00) (00 71 1C) (00 71 39) (00 71 55) (00 71 71) (00 55 71) (00 39 71) (00 1C 71)
(39 39 71) (45 39 71) (55 39 71) (61 39 71) (71 39 71) (71 39 61) (71 39 55) (71 39 45)
(71 39 39) (71 45 39) (71 55 39) (71 61 39) (71 71 39) (61 71 39) (55 71 39) (45 71 39)
(39 71 39) (39 71 45) (39 71 55) (39 71 61) (39 71 71) (39 61 71) (39 55 71) (39 45 71)
(51 51 71) (59 51 71) (61 51 71) (69 51 71) (71 51 71) (71 51 69) (71 51 61) (71 51 59)
(71 51 51) (71 59 51) (71 61 51) (71 69 51) (71 71 51) (69 71 51) (61 71 51) (59 71 51)
(51 71 51) (51 71 59) (51 71 61) (51 71 69) (51 71 71) (51 69 71) (51 61 71) (51 59 71)
(00 00 41) (10 00 41) (20 00 41) (31 00 41) (41 00 41) (41 00 31) (41 00 20) (41 00 10)
(41 00 00) (41 10 00) (41 20 00) (41 31 00) (41 41 00) (31 41 00) (20 41 00) (10 41 00)
(00 41 00) (00 41 10) (00 41 20) (00 41 31) (00 41 41) (00 31 41) (00 20 41) (00 10 41)
(20 20 41) (28 20 41) (31 20 41) (39 20 41) (41 20 41) (41 20 39) (41 20 31) (41 20 28)
(41 20 20) (41 28 20) (41 31 20) (41 39 20) (41 41 20) (39 41 20) (31 41 20) (28 41 20)
(20 41 20) (20 41 28) (20 41 31) (20 41 39) (20 41 41) (20 39 41) (20 31 41) (20 28 41)
(2D 2D 41) (31 2D 41) (35 2D 41) (3D 2D 41) (41 2D 41) (41 2D 3D) (41 2D 35) (41 2D 31)
(41 2D 2D) (41 31 2D) (41 35 2D) (41 3D 2D) (41 41 2D) (3D 41 2D) (35 41 2D) (31 41 2D)
(2D 41 2D) (2D 41 31) (2D 41 35) (2D 41 3D) (2D 41 41) (2D 3D 41) (2D 35 41) (2D 31 41)
(00 00 00) (00 00 00) (00 00 00) (00 00 00) (00 00 00) (00 00 00) (00 00 00) (00 00 00))")))
(defpackage #:snippets/simple-graphics
(:nicknames #:sg)
(:use #:cl)
(:import-from #:sdl2)
(:import-from #:sdl2-gfx)
(:import-from #:autowrap)
(:import-from #:plus-c)
(:import-from #:alexandria)
(:import-from #:snippets/simple-graphics-data)
(:import-from #:dufy)
(:import-from #:sb-ext)
(:import-from #:sb-sys)
(:import-from #:sb-posix)
(:import-from #:cffi)
(:export
#:gradient
#:fs
#:with-graphics
#:screen-width
#:screen-height
#:*event*
#:event-case
#:pset
#:line
#:rect
#:frect
#:circle
#:fcircle
#:tri
#:ftri
#:cls
#:text
#:frame-loop
#:again
#:overlay
#:ovclear
#:ovblit
#:ovrecord))
(in-package #:snippets/simple-graphics)
(defvar *window* nil)
(defvar *window-renderer* nil)
(defvar *renderer* nil)
(defvar *width* nil)
(defvar *height* nil)
(defvar *fps-manager* nil)
(defun vector-to-c-octets (vector)
(let* ((size (length vector))
(wrapper (autowrap:alloc :unsigned-char size)))
(dotimes (i size)
(setf (autowrap:c-aref wrapper i :unsigned-char) (aref vector i)))
wrapper))
(defvar *font*
(vector-to-c-octets snippets/simple-graphics-data:*10x20-font*))
(defvar *vga-palette*
(map 'vector
(lambda (rgb)
(destructuring-bind (r g b) rgb
(logior (ash #xFF 24)
(ash b 16)
(ash g 8)
(ash r 0))))
snippets/simple-graphics-data:*vga-palette*))
(defvar *b/w-palette*
(make-array 256 :initial-contents
(loop for i from 0 below 256
collect (logior (ash #xFF 24)
(ash i 16)
(ash i 8)
(ash i 0)))))
(defvar *palette* nil)
(defun palette (palette-designator)
(case palette-designator
(:vga *vga-palette*)
(:b/w *b/w-palette*)
(t palette-designator)))
(defun gradient (control-points)
(let ((n (length control-points))
(palette (make-array 256)))
(assert (>= n 2))
(labels ((interpolate (start-color end-color start size more)
(destructuring-bind (sr sg sb) start-color
(destructuring-bind (er eg eb) end-color
(let ((alpha-dec (/ 1.0 (1- size)))
(alpha 1.0))
(dotimes (i size)
(let* ((beta (- 1 alpha))
(ir (+ (* alpha sr) (* beta er)))
(ig (+ (* alpha sg) (* beta eg)))
(ib (+ (* alpha sb) (* beta eb))))
(setf (aref palette (+ i start))
(logior (ash (truncate (* ir 255)) 0)
(ash (truncate (* ig 255)) 8)
(ash (truncate (* ib 255)) 16)
(ash #xFF 24))))
(decf alpha alpha-dec)))))
(if more
(interpolate end-color
(first more)
(+ start size)
(if (null (rest more))
(- 256 (+ start size))
size)
(rest more))
palette)))
(interpolate (first control-points)
(second control-points)
0
(round 256 (1- n))
(cddr control-points)))))
(defun call-with-graphics (function width height frame-rate palette fullscreen)
(sdl2:with-init (:video)
(let ((*width* width)
(*height* height))
(multiple-value-bind (w h flags)
(if fullscreen
(values 0 0 '(:shown :fullscreen-desktop))
(values width height '(:shown)))
(sdl2:with-window (*window* :w w :h h :flags flags)
(sdl2:with-renderer (*renderer* *window*)
(when fullscreen
(sdl2-ffi.functions:sdl-set-hint sdl2-ffi:+sdl-hint-render-scale-quality+
"linear")
(sdl2-ffi.functions:sdl-render-set-logical-size *renderer* width height))
(let ((*window-renderer* *renderer*)
(*palette* (palette palette)))
(sdl2-ffi.functions:gfx-primitives-set-font *font* 10 20)
(plus-c:c-let ((fps-manager sdl2-ffi:fp-smanager :free t))
(let ((*fps-manager* (and frame-rate fps-manager)))
(when *fps-manager*
(sdl2-ffi.functions:sdl-init-framerate (autowrap:ptr *fps-manager*))
(sdl2-ffi.functions:sdl-set-framerate (autowrap:ptr *fps-manager*)
frame-rate))
(funcall function))))))))))
(defvar *fullscreen* nil)
(defmacro fs (&body forms)
`(let ((*fullscreen* t))
,@forms))
(defmacro with-graphics ((&key (width 640) (height 480) (frame-rate 30)
(palette :vga) (fullscreen '*fullscreen*))
&body forms)
`(block nil
(call-with-graphics (lambda () ,@forms)
,width
,height
,frame-rate
,palette
,fullscreen)))
(defun screen-width ()
*width*)
(defun screen-height ()
*height*)
(defmacro cast-to-int (value)
`(the fixnum (floor (+ ,value 0.5))))
(defun color-from-palette (c)
(if (null *palette*)
c
(aref *palette* (cast-to-int c))))
(defun pset (x y c)
(sdl2-ffi.functions:pixel-color *renderer*
(cast-to-int x)
(cast-to-int y)
(color-from-palette c)))
(defun line (x1 y1 x2 y2 c)
(sdl2-ffi.functions:line-color *renderer*
(cast-to-int x1)
(cast-to-int y1)
(cast-to-int x2)
(cast-to-int y2)
(color-from-palette c)))
(defun rect (x1 y1 x2 y2 c)
(let* ((x1 (cast-to-int x1))
(y1 (cast-to-int y1))
(x2 (cast-to-int x2))
(y2 (cast-to-int y2)))
(sdl2-ffi.functions:rectangle-color *renderer*
x1
y1
x2
y2
(color-from-palette c))))
(defun frect (x1 y1 x2 y2 c)
(sdl2-ffi.functions:box-color *renderer*
x1
y1
x2
y2
(color-from-palette c)))
(defun circle (x y r c)
(sdl2-ffi.functions:circle-color *renderer*
(cast-to-int x)
(cast-to-int y)
(cast-to-int r)
(color-from-palette c)))
(defun fcircle (x y r c)
(sdl2-ffi.functions:filled-circle-color *renderer*
(cast-to-int x)
(cast-to-int y)
(cast-to-int r)
(color-from-palette c)))
(defun rad (x)
(* x (/ pi 180.0)))
(defun rot (p a)
(let ((ca (cos a))
(sa (sin a))
(x (realpart p))
(y (imagpart p)))
(complex (round (- (* x ca) (* y sa)))
(round (+ (* x sa) (* y ca))))))
(defun trans (p x y)
(+ p (complex x y)))
(defun tri (cx cy r c &optional (a 0))
(setf a (rad a))
(let ((p1 (trans (rot (complex (- r) r) a) cx cy))
(p2 (trans (rot (complex (+ r) r) a) cx cy))
(p3 (trans (rot (complex 0 (- r)) a) cx cy)))
(sdl2-ffi.functions:trigon-color *renderer*
(cast-to-int (realpart p1))
(cast-to-int (imagpart p1))
(cast-to-int (realpart p2))
(cast-to-int (imagpart p2))
(cast-to-int (realpart p3))
(cast-to-int (imagpart p3))
(color-from-palette c))))
(defun ftri (cx cy r c &optional (a 0))
(setf a (rad a))
(let ((p1 (trans (rot (complex (- r) r) a) cx cy))
(p2 (trans (rot (complex (+ r) r) a) cx cy))
(p3 (trans (rot (complex 0 (- r)) a) cx cy)))
(sdl2-ffi.functions:filled-trigon-color *renderer*
(cast-to-int (realpart p1))
(cast-to-int (imagpart p1))
(cast-to-int (realpart p2))
(cast-to-int (imagpart p2))
(cast-to-int (realpart p3))
(cast-to-int (imagpart p3))
(color-from-palette c))))
(defun cls (&optional (c 0))
(let ((color (color-from-palette c)))
(sdl2:set-render-draw-color *window-renderer*
(ldb (byte 8 0) color)
(ldb (byte 8 8) color)
(ldb (byte 8 16) color)
(ldb (byte 8 24) color))
(sdl2:render-clear *window-renderer*)))
(defun text (x y c string)
(sdl2-ffi.functions:string-color *renderer*
(cast-to-int x)
(cast-to-int y)
string
(color-from-palette c)))
(defvar *overlays*
(make-array 0 :adjustable t :initial-element nil))
(defvar *overlay-color-key*
#xFFFF00FF)
(defstruct overlay
renderer
surface)
(defun overlay (n)
(when (null n)
(setf *renderer* *window-renderer*)
(return-from overlay (values)))
(when (>= n (length *overlays*))
(setf *overlays*
(adjust-array *overlays* (1+ n) :initial-element nil)))
(symbol-macrolet ((overlay (aref *overlays* n)))
(when (null overlay)
(let* ((surface (sdl2:create-rgb-surface *width*
*height*
32))
(renderer (sdl2:create-software-renderer surface)))
(sdl2:set-color-key surface :true *overlay-color-key*)
(let ((*renderer* renderer))
(ovclear))
(setf overlay
(make-overlay :surface surface
:renderer renderer))))
(setf *renderer* (overlay-renderer overlay))
(values)))
(defun ovclear ()
(let ((color *overlay-color-key*))
(sdl2:set-render-draw-color *renderer*
(ldb (byte 8 0) color)
(ldb (byte 8 8) color)
(ldb (byte 8 16) color)
(ldb (byte 8 24) color))
(sdl2:render-clear *renderer*))
(values))
(defun ovblit (&optional numbers)
(let ((*renderer* *window-renderer*))
(if numbers
(dolist (k numbers)
(when (array-in-bounds-p *overlays* k)
(let ((overlay (aref *overlays* k)))
(when overlay
(let ((texture (sdl2:create-texture-from-surface *renderer*
(overlay-surface overlay))))
(unwind-protect
(sdl2:render-copy *renderer* texture)
(sdl2:destroy-texture texture)))))))
(map nil (lambda (overlay)
(when overlay
(let ((texture (sdl2:create-texture-from-surface *renderer*
(overlay-surface overlay))))
(unwind-protect
(sdl2:render-copy *renderer* texture)
(sdl2:destroy-texture texture)))))
*overlays*))
(values)))
(defvar *record-output-directory*
"/tmp/")
(defun make-record-output-filename ()
(concatenate 'string *record-output-directory* (datestring) ".mp4"))
(defun datestring ()
(multiple-value-bind (s m h dd mm yy) (get-decoded-time)
(declare (ignore s))
(format nil "~4,'0D-~2,'0D-~2,'0DT~2,'0D~2,'0D" yy mm dd h m)))
(defun start-ffmpeg-process (width height frame-rate output-file)
;; FFmpeg options baseline comes from
;; https://gitlab.com/asciiphil/advent-of-code/-/blob/master/visualization.lisp
(sb-ext:run-program
"ffmpeg"
(list "-loglevel" "error"
"-nostats"
"-nostdin"
"-f" "rawvideo"
"-s" (format nil "~Dx~D" width height)
"-pix_fmt" "bgra"
"-r" (format nil "~D" frame-rate)
"-i" "-"
;; No audio
"-an"
"-f" "mp4"
;; x264: See https://trac.ffmpeg.org/wiki/Encode/H.264 ---
;; For truly lossless video we may need libx264rgb.
"-c:v" "libx264"
"-preset" "veryslow"
;; Constant rate factor: 0-lossless/23-default/51-worst
"-crf" "17"
"-tune" "animation"
"-pix_fmt" "yuv420p"
"-profile:v" "main"
;; See https://en.wikipedia.org/wiki/H264#Levels
"-level" "3.1"
;; I tried this to eliminate the overlay's color key, but it
;; leaves artifacts coming from SDL rendering. Instead it
;; may be best to set *OVERLAY-COLOR-KEY* to #xFF000000 when
;; recording.
;;
;; "-filter_complex"
;; "[0]split=2[bg][fg];
;; [bg]drawbox=c=black@1:replace=1:t=fill[bg];
;; [fg]colorkey=color=ff00ff:similarity=0.01:blend=0.0[fg];
;; [bg][fg]overlay[out]"
;; "-map" "[out]"
"-y"
output-file)
:input :stream
:wait nil
:search t))
(defvar *ffmpeg-process* nil)
(defun ovrecord (&optional (number 0))
(when (array-in-bounds-p *overlays* number)
(let ((overlay (aref *overlays* number)))
(when overlay
(let* ((surface (overlay-surface overlay))
(width (sdl2:surface-width surface))
(height (sdl2:surface-height surface)))
(when (null *ffmpeg-process*)
(let ((frame-rate (sdl2-ffi.functions:sdl-get-framerate (autowrap:ptr *fps-manager*)))
(output-file (make-record-output-filename)))
(setf *ffmpeg-process* (start-ffmpeg-process width height frame-rate output-file))))
(when (sb-ext:process-alive-p *ffmpeg-process*)
(let* ((input (sb-ext:process-input *ffmpeg-process*))
(fd (sb-sys:fd-stream-fd input))
(buf (sdl2:surface-pixels surface))
(count (* height (sdl2:surface-pitch surface))))
(loop while (plusp count)
do (let ((bytes-written (sb-posix:write fd buf count)))
(cffi:inc-pointer buf bytes-written)
(decf count bytes-written))))))))))
(defun ovfree ()
(setf *renderer* *window-renderer*)
(map nil (lambda (overlay)
(when overlay
(sdl2:destroy-renderer (overlay-renderer overlay))
(sdl2:free-surface (overlay-surface overlay))))
*overlays*)
(setf *overlays* (adjust-array *overlays* 0 :initial-element nil))
(when *ffmpeg-process*
(when (sb-ext:process-alive-p *ffmpeg-process*)
(close (sb-ext:process-input *ffmpeg-process*))
(sb-ext:process-wait *ffmpeg-process*))
(setf *ffmpeg-process* nil))
(values))
(defvar *event* nil)
(defvar *again* nil)
(defun call-with-frame-function (frame-function &key (update :idle))
(let ((*again* nil)
(quit nil))
(unwind-protect
(flet ((redraw (&rest event)
(when (and (not quit)
(or *again*
(and (eq update :one-shot)
(and (eq (car event) :window)
(eq (cadr event) :exposed)))
(and (eq update :event)
(not (eq (car event) :idle)))
(and (eq update :idle)
(eq (car event) :idle))
(eq update :all)))
(setf *again* nil)
(let ((*event* event)
(*renderer* *window-renderer*))
(funcall frame-function)
(sdl2:render-present *window-renderer*)))))
;; Recursive event loop is used because sometimes after an
;; abort we'll somehow have SDL2::*EVENT-LOOP* remain true.
(sdl2:with-event-loop (:recursive t)
(:quit () t)
(:keydown
(:keysym keysym)
(let ((scancode (sdl2:scancode keysym)))
(cond ((eq scancode :scancode-escape)
(sdl2:push-event :quit)
(setf quit t))
(t (redraw :key-down scancode)))))
(:keyup
(:keysym keysym)
(let ((scancode (sdl2:scancode keysym)))
(unless (eq scancode :scancode-escape)
(redraw :key-up scancode))))
(:mousemotion
(:x x :y y)
(redraw :mouse-move x y))
(:mousebuttondown
(:button button :x x :y y)
(redraw :mouse-down button x y))
(:mousebuttonup
(:button button :x x :y y)
(redraw :mouse-up button x y))
(:idle
()
(redraw :idle)
(when *fps-manager*
(sdl2-ffi.functions:sdl-framerate-delay (autowrap:ptr *fps-manager*))))
(:windowevent
(:event event)
(let ((id (autowrap:enum-key 'sdl2-ffi:sdl-window-event-id event)))
(redraw :window id)))))
(ovfree))))
(defmacro frame-loop ((&key (update ':idle)) &body forms)
`(call-with-frame-function (lambda () ,@forms) :update ,update))
(defun again ()
(setf *again* t))
(defmacro event-case (&body clauses)
`(alexandria:destructuring-case *event*
,@clauses))
;;;; Examples
(defun pixels-1 ()
"Draw random points."
(with-graphics ()
(frame-loop ()
(pset (random (screen-width)) (random (screen-height))
(random 256)))))
(defclass star ()
((x :initarg :x :accessor x)
(y :initarg :y :accessor y)
(s :initarg :s :accessor s)))
(defparameter *speeds* 4)
(defun pixels-2 ()
"Simulate 2D starfield."
(with-graphics ()
(let ((stars (loop repeat 200 collect (random-star))))
(frame-loop ()
(mapc #'erase-star stars)
(mapc #'move-star stars)
(mapc #'draw-star stars)))))
(defun random-star ()
(make-instance 'star
:x (random (screen-width))
:y (random (screen-height))
:s (1+ (random *speeds*))))
(defun erase-star (star)
(pset (x star) (y star) 0))
(defun draw-star (star)
(let ((c (+ 15.0 (* (s star) (/ (- 31.0 15.0) *speeds*)))))
(pset (x star) (y star) (floor c))))
(defun move-star (star)
(decf (x star) (s star))
(when (or (minusp (x star)) (minusp (y star)))
(setf (x star) (- (screen-width) 1))
(setf (y star) (random (screen-height)))
(setf (s star) (1+ (random *speeds*)))))
(defvar *virtual-screen* nil)
(defmacro with-virtual-screen ((width height) &body body)
`(let ((*virtual-screen*
(make-array (list ,height ,width)
:element-type '(unsigned-byte 8)
:initial-element 0)))
,@body))
(defun psetv (x y c)
(setf x (cast-to-int x))
(setf y (cast-to-int y))
(when (and (>= x 0) (< x (screen-width))
(>= y 0) (< y (screen-width)))
(setf (aref *virtual-screen* y x)
(min 255 (max 0 (cast-to-int c))))
(pset x y c)))
(defun pointv (x y)
(setf x (cast-to-int x))
(setf y (cast-to-int y))
(if (and (>= x 0) (< x (screen-width))
(>= y 0) (< y (screen-height)))
(aref *virtual-screen* y x)
0))
(defun clsv ()
(fill (make-array (array-total-size *virtual-screen*)
:displaced-to *virtual-screen*
:element-type '(unsigned-byte 8))
0)
(cls))
(defun pixels-3 ()
"Draw noise."
(with-graphics (:width 320 :height 200 :palette :b/w)
(with-virtual-screen (320 200)
(frame-loop (:update :one-shot)
(clsv)
(psetv 0 0 (1+ (random 192)))
(psetv 319 0 (1+ (random 192)))
(psetv 319 199 (1+ (random 192)))
(psetv 0 199 (1+ (random 192)))
(subdivide 0 0 319 199)))))
(defun subdivide (x1 y1 x2 y2)
(when (and (< (- x2 x1) 2) (< (- y2 y1)))
(return-from subdivide))
(let ((x (floor (+ x1 x2) 2))
(y (floor (+ y1 y2) 2)))
(adjust x1 y1 x y1 x2 y1)
(adjust x2 y1 x2 y x2 y2)
(adjust x1 y2 x y2 x2 y2)
(adjust x1 y1 x1 y x1 y2)
(when (= 0 (pointv x y))
(psetv x
y
(truncate (+ (pointv x1 y1) (pointv x2 y1)
(pointv x1 y2) (pointv x2 y2))
4)))
(subdivide x1 y1 x y)
(subdivide x y1 x2 y)
(subdivide x y x2 y2)
(subdivide x1 y x y2)))
(defun adjust (xa ya x y xb yb)
(when (/= 0 (pointv x y))
(return-from adjust))
(let* ((d (+ (abs (- xa xb)) (abs (- ya yb))))
(v (+ (truncate (+ (pointv xa ya) (pointv xb yb)) 2)
(* d 2.0 (- (random 1.0) 0.5)))))
(psetv x y (min 192 (max 1 v)))))
(defun pixels-4 (&optional (c #C(-0.1 0.8)))
"Draw Julia set."
(with-graphics (:palette :b/w)
(frame-loop (:update :one-shot)
(let ((mx (screen-width))
(my (screen-height)))
(dotimes (y my)
(dotimes (x mx)
(do ((n (complex (+ -2.0 (/ x (/ mx 4.0)))
(- 2.0 (/ y (/ my 4.0))))
(+ (* n n) c))
(i 0 (1+ i)))
((or (>= i 255)
(> (+ (* (realpart n) (realpart n))
(* (imagpart n) (imagpart n)))
4.0))
(pset x y (min 255 (* 6 (if (= i 255) 0 i))))))))))))
(defun pixels-5 ()
"Draw flames."
;; See https://nullprogram.com/blog/2020/04/30/
(with-graphics (:width 320 :height 200
:palette (gradient '((0.0 0.0 0.0) (0.1 0.1 0.1)
(1.0 0.0 0.0) (1.0 1.0 0.0)
(1.0 1.0 1.0))))
(with-virtual-screen (320 200)
(let ((first-frame t))
(frame-loop ()
(cond (first-frame
(dotimes (x (screen-width))
(psetv x (1- (screen-height)) 170))
(setf first-frame nil))
(t
(loop for y from 0 to (- (screen-height) 2)
do (loop for x from 1 to (- (screen-width) 1)
for sx = (+ x (- (random 3) 1))
for sy = (+ y (random 2))
do (psetv x y
(max 0
(- (pointv sx sy)
(random 2)))))))))))))
(defun pixels-6 (&key (shapes '(:line :rect :circle :triangle))
(fill :sometimes))
"Draw random shapes."
(with-graphics ()
(frame-loop ()
(when shapes
(let ((shape (alexandria:random-elt shapes))
(filled (ecase fill
(:always t)
(:never nil)
(:sometimes (zerop (random 2))))))
(ecase shape
(:line
(let ((x1 (random (screen-width)))
(y1 (random (screen-height)))
(x2 (random (screen-width)))
(y2 (random (screen-height)))
(c (random 256)))
(line x1 y1 x2 y2 c)))
(:rect
(let ((x1 (random (screen-width)))
(y1 (random (screen-height)))
(x2 (random (screen-width)))
(y2 (random (screen-height)))
(c (random 256)))
(if filled
(frect x1 y1 x2 y2 c)
(rect x1 y1 x2 y2 c))))
(:circle
(let ((x (random (screen-width)))
(y (random (screen-height)))
(r (random (truncate (min (screen-width) (screen-height)) 2)))
(c (random 256)))
(if filled
(fcircle x y r c)
(circle x y r c))))
(:triangle
(let ((cx (random (screen-width)))
(cy (random (screen-height)))
(r (random (truncate (min (screen-width) (screen-height)) 2)))
(c (random 256))
(a (random 360)))
(if filled
(ftri cx cy r c a)
(tri cx cy r c a))))))))))
(defun rectangular-spiral (aspect-ratio)
(let* ((dy 4)
(dx (* dy aspect-ratio))
(x 0)
(y 0))
(lambda (time)
(let ((sign (if (< time 0) -1 +1)))
(case (logand (- (isqrt (1+ (* 4 sign time))) sign) 3)
(0 (incf x dx))
(1 (incf y dy))
(2 (decf x dx))
(3 (decf y dy)))
(complex x y)))))
(defun archimedean-spiral (aspect-ratio)
(lambda (time)
(let ((j (* time 0.1)))
(complex (* aspect-ratio j (cos j))
(* j (sin j))))))
(defun pixels-7 (&optional function)
"Plot position over time."
(when (null function)
(setf function
(if (zerop (random 2))
(rectangular-spiral 1)
(archimedean-spiral 1))))
(with-graphics (:width 500 :height 500)
(let ((time 0))
(frame-loop (:update :idle)
(let ((point (funcall function time)))
(pset (+ (realpart point) 250)
(+ (imagpart point) 250)
15)
(incf time))))))
(defun pixels-8 (&optional (palette :vga))
"Show palette colors."
(with-graphics (:width 256 :height 256 :palette palette)
(frame-loop ()
(dotimes (i 16)
(dotimes (j 16)
(let* ((color (+ (* i 16) j))
(x1 (* j 16))
(x2 (+ (* j 16) 15))
(y1 (* i 16))
(y2 (+ (* i 16) 15)))
(frect x1 y1 x2 y2 color)))))))
(defun pixels-9 (&optional (function #'identity))
"Domain coloring of a complex function."
(let* ((x-min -3.0)
(y-min -3.0)
(x-max +3.0)
(y-max +3.0)
(step 0.01)
(x-pad 20)
(y-pad 20)
(width (truncate (- x-max x-min) step))
(height (truncate (- y-max y-min) step)))
(with-graphics (:width (+ width x-pad) :height (+ height y-pad) :palette nil)
(frame-loop (:update :one-shot)
(do ((y y-min (+ y step)))
((> y y-max))
(do ((x x-min (+ x step)))
((> x x-max))
(pset (truncate (+ (* (/ (- x x-min) (- x-max x-min)) width)
(truncate x-pad 2)))
(truncate (+ (* (/ (- y y-min) (- y-max y-min)) height)
(truncate y-pad 2)))
(complex-color (funcall function (complex x y))))))))))
(defun complex-to-hsl (complex)
(values (* (/ 180 pi) (phase complex))
1.0
(* (/ 2 pi) (atan (abs complex)))))
(defun complex-to-rgb (complex)
(multiple-value-bind (h s l) (complex-to-hsl complex)
(multiple-value-bind (r g b) (dufy:hsl-to-rgb h s l)
(values (truncate (* 255 r))
(truncate (* 255 g))
(truncate (* 255 b))))))
(defun complex-color (complex)
(multiple-value-bind (r g b) (complex-to-rgb complex)
(logior (ash #xFF 24)
(ash b 16)
(ash g 8)
(ash r 0))))
(defun pixels-10 (&key (detent 0.2) (grid 0.25) snap)
"Interactive graphics."
;; Inspired by
;; https://lobste.rs/s/gybecd/most_useful_math_formulas#c_dllozz
(with-graphics ()
(let ((x 0)
(y 0)
(w (screen-width))
(h (screen-height)))
(frame-loop (:update :event)
(event-case
((:mouse-move mx my)
(setf x (/ mx w) y (/ my h))))
(cls)
(circle (* (detent x detent grid snap) w) (* y h) 10 9)))))
(defun round-to (n quantum)
(* (round n quantum) quantum))
(defun detent (n detent grid &optional snap)
(let ((r1 (round-to n grid)))
(cond ((< (abs (- n r1)) (/ detent 2))
r1)
(snap
n)
(t
(let ((r2 (if (< n r1)
(- r1 (/ detent 2))
(+ r1 (/ detent 2)))))
(+ r1 (/ (* (- n r2) grid) (- grid detent))))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment