1 # Return colors 'near' a given r/g/b value (expressed in hex) 2 # If we did this rigorously we'd need to implement cosines. So we won't. 3 # 4 # To build: 5 # $ ./translate colors.mu 6 # 7 # Example session: 8 # $ qemu-system-i386 code.img 9 # Enter 3 hex bytes for r, g, b (lowercase; no 0x prefix) separated by a single space> aa 0 aa 10 # 5 11 # This means only color 5 in the default palette is similar to #aa00aa. 12 13 fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { 14 var in-storage: (stream byte 0x10) 15 var in/esi: (addr stream byte) <- address in-storage 16 { 17 # print prompt 18 var x/eax: int <- draw-text-rightward screen, "Enter 3 hex bytes for r, g, b (lowercase; no 0x prefix) separated by a single space> ", 0x10/x, 0x80/xmax, 0x28/y, 3/fg/cyan, 0/bg 19 # read line from keyboard 20 clear-stream in 21 { 22 draw-cursor screen, 0x20/space 23 var key/eax: byte <- read-key keyboard 24 compare key, 0xa/newline 25 break-if-= 26 compare key, 0 27 loop-if-= 28 var key2/eax: int <- copy key 29 append-byte in, key2 30 var g/eax: grapheme <- copy key2 31 draw-grapheme-at-cursor screen, g, 0xf/fg, 0/bg 32 move-cursor-right 0 33 loop 34 } 35 clear-screen screen 36 # parse 37 var a/ecx: int <- copy 0 38 var b/edx: int <- copy 0 39 var c/ebx: int <- copy 0 40 # a, b, c = r, g, b 41 a, b, c <- parse in 42 #? set-cursor-position screen, 0x10/x, 0x1a/y 43 #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen screen, a, 7/fg, 0/bg 44 #? draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, " ", 7/fg, 0/bg 45 #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen screen, b, 7/fg, 0/bg 46 #? draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, " ", 7/fg, 0/bg 47 #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen screen, c, 7/fg, 0/bg 48 a, b, c <- hsl a, b, c 49 # return all colors in the same quadrant in h, s and l 50 print-nearby-colors screen, a, b, c 51 # 52 loop 53 } 54 } 55 56 # read exactly 3 words in a single line 57 # Each word consists of exactly 1 or 2 hex bytes. No hex prefix. 58 fn parse in: (addr stream byte) -> _/ecx: int, _/edx: int, _/ebx: int { 59 # read first byte of r 60 var tmp/eax: byte <- read-byte in 61 { 62 var valid?/eax: boolean <- hex-digit? tmp 63 compare valid?, 0/false 64 break-if-!= 65 abort "invalid byte 0 of r" 66 } 67 tmp <- fast-hex-digit-value tmp 68 var r/ecx: int <- copy tmp 69 #? set-cursor-position 0/screen, 0x10/x, 0x10/y 70 #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, r, 7/fg, 0/bg 71 # read second byte of r 72 tmp <- read-byte in 73 { 74 { 75 var valid?/eax: boolean <- hex-digit? tmp 76 compare valid?, 0/false 77 } 78 break-if-= 79 r <- shift-left 4 80 tmp <- fast-hex-digit-value tmp 81 #? { 82 #? var foo/eax: int <- copy tmp 83 #? set-cursor-position 0/screen, 0x10/x, 0x11/y 84 #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, foo, 7/fg, 0/bg 85 #? } 86 r <- add tmp 87 #? { 88 #? set-cursor-position 0/screen, 0x10/x, 0x12/y 89 #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, r, 7/fg, 0/bg 90 #? } 91 tmp <- read-byte in # skip space 92 } 93 # read first byte of g 94 var tmp/eax: byte <- read-byte in 95 { 96 var valid?/eax: boolean <- hex-digit? tmp 97 compare valid?, 0/false 98 break-if-!= 99 abort "invalid byte 0 of g" 100 } 101 tmp <- fast-hex-digit-value tmp 102 var g/edx: int <- copy tmp 103 #? set-cursor-position 0/screen, 0x10/x, 0x13/y 104 #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, g, 7/fg, 0/bg 105 # read second byte of g 106 tmp <- read-byte in 107 { 108 { 109 var valid?/eax: boolean <- hex-digit? tmp 110 compare valid?, 0/false 111 } 112 break-if-= 113 g <- shift-left 4 114 tmp <- fast-hex-digit-value tmp 115 #? { 116 #? var foo/eax: int <- copy tmp 117 #? set-cursor-position 0/screen, 0x10/x, 0x14/y 118 #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, foo, 7/fg, 0/bg 119 #? } 120 g <- add tmp 121 #? { 122 #? set-cursor-position 0/screen, 0x10/x, 0x15/y 123 #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, g, 7/fg, 0/bg 124 #? } 125 tmp <- read-byte in # skip space 126 } 127 # read first byte of b 128 var tmp/eax: byte <- read-byte in 129 { 130 var valid?/eax: boolean <- hex-digit? tmp 131 compare valid?, 0/false 132 break-if-!= 133 abort "invalid byte 0 of b" 134 } 135 tmp <- fast-hex-digit-value tmp 136 var b/ebx: int <- copy tmp 137 #? set-cursor-position 0/screen, 0x10/x, 0x16/y 138 #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, b, 7/fg, 0/bg 139 # read second byte of b 140 { 141 { 142 var done?/eax: boolean <- stream-empty? in 143 compare done?, 0/false 144 } 145 break-if-!= 146 tmp <- read-byte in 147 { 148 var valid?/eax: boolean <- hex-digit? tmp 149 compare valid?, 0/false 150 } 151 break-if-= 152 b <- shift-left 4 153 tmp <- fast-hex-digit-value tmp 154 #? { 155 #? var foo/eax: int <- copy tmp 156 #? set-cursor-position 0/screen, 0x10/x, 0x17/y 157 #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, foo, 7/fg, 0/bg 158 #? } 159 b <- add tmp 160 #? { 161 #? set-cursor-position 0/screen, 0x10/x, 0x18/y 162 #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, b, 7/fg, 0/bg 163 #? } 164 } 165 return r, g, b 166 } 167 168 # no error checking 169 fn fast-hex-digit-value in: byte -> _/eax: byte { 170 var result/eax: byte <- copy in 171 compare result, 0x39 172 { 173 break-if-> 174 result <- subtract 0x30/0 175 return result 176 } 177 result <- subtract 0x61/a 178 result <- add 0xa/10 179 return result 180 } 181 182 fn print-nearby-colors screen: (addr screen), h: int, s: int, l: int { 183 #? set-cursor-position screen, 0x10/x, 0x1c/y 184 #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen screen, h, 7/fg, 0/bg 185 #? draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, " ", 7/fg, 0/bg 186 #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen screen, s, 7/fg, 0/bg 187 #? draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, " ", 7/fg, 0/bg 188 #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen screen, l, 7/fg, 0/bg 189 # save just top 2 bits of each, so that we narrow down to 1/64th of the volume 190 shift-right h, 6 191 shift-right s, 6 192 shift-right l, 6 193 #? set-cursor-position screen, 0x10/x, 0x1/y 194 #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen screen, h, 7/fg, 0/bg 195 #? draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, " ", 7/fg, 0/bg 196 #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen screen, s, 7/fg, 0/bg 197 #? draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, " ", 7/fg, 0/bg 198 #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen screen, l, 7/fg, 0/bg 199 var a/ecx: int <- copy 0 200 var b/edx: int <- copy 0 201 var c/ebx: int <- copy 0 202 var color/eax: int <- copy 0 203 var y/esi: int <- copy 2 204 { 205 compare color, 0x100 206 break-if->= 207 a, b, c <- color-rgb color 208 a, b, c <- hsl a, b, c 209 a <- shift-right 6 210 b <- shift-right 6 211 c <- shift-right 6 212 { 213 compare a, h 214 break-if-!= 215 compare b, s 216 break-if-!= 217 compare c, l 218 break-if-!= 219 set-cursor-position screen, 0x10/x, y 220 draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen screen, color, 7/fg, 0/bg 221 set-cursor-position screen, 0x14/x, y 222 draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, " ", 7/fg, 0/bg 223 draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, " ", 0/fg, color 224 #? draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, " ", 7/fg, 0/bg 225 #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen screen, a, 7/fg, 0/bg 226 #? draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, " ", 7/fg, 0/bg 227 #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen screen, b, 7/fg, 0/bg 228 #? draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, " ", 7/fg, 0/bg 229 #? draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen screen, c, 7/fg, 0/bg 230 y <- increment 231 } 232 color <- increment 233 loop 234 } 235 }