More : Colors ( - More ] Forth ┄──────────────────────┄ [ July 25, 2024 Finding Better Colors ┄───────────────────┄ : define [ execute ] compile { postpone % tag ~ variable ( comment Showing Numbers ┄─────────────┄ Hex: $ff00ff Decimal: #123 cf x86-64 ┄───────┄ • 64-bit data + return stack. • 32-bit addresses and value by default. • C "harness" to boot + provide I/O • Windows and now Linux support • Maybe UEFI Boot next? Language Goals ┄────────────┄ • Try to use Chuck's quirks: ◦ : - ] invert ◦ : or ] xor ◦ : if ( use x86 zero flag, no stack effect ◦ : -if ( use x86 sign flag, no stack effect ◦ : push ] >r : pop ] r> ◦ : @ ( : ! ( etc. use word sized indexing ◦ Use A register, : @+ ( : !+ ◦ Emit literals on [ immediate ] to green Why colorForth? ┄─────────────┄ • Forth is about naming some things... ] variable • But implying other things. ] rot + push + pop • It is both mnemonic and pithy. • Color is [ joyful! • It's even : SIMPLER ( than conventional Forth. • Interpret/compile is just a dispatch table! create colors ' none , ' exec , ' none , ' define , ' comp , ' none , ' *comp , ' defer , ' *exec , ' none , ' none , ' none , ' var , ' none , ' none , ' none , : interpret ( a n -- ) 0 do dup @ dup $f and cells color + @ execute cell+ loop ; ( dictionary loop and utils : nope ] @nope @ execute ; : ,dict ] #4 vocab @ 4/ +! vocab @ 4/ @ 4/ ! ; : ?cnot ] lastc @ $f0 and or drop ; : ?lit ] $10 ?cnot if $80 ?cnot if ; then then push literal pop ; : nah? ( wd-wdf ] 2dup @ ? if or #15 - and ; then nip ? ; : find ] nah? if drop 1- 1- find ; then drop nip 1- @ ? ; ( implementation of all color tags : define ] chere ,dict ,dict ; : comp ] ?lit dup push mvocab find if rdrop execute ; then ] drop pop dup fvocab find if ,compile drop ; then drop nope ; : *comp ] ?lit #5 sar literal ; : exec ] dup push fvocab find if rdrop execute ; then drop pop nope ; : *exec ] #5 sar ; : post ] dup mvocab find if ,compile drop ; then drop nope ; : var ] define pop pop pop 1+ dup literal push push push { ; ] ; : none ] drop ; ( tag dispatch table : ,t ] over @tbl ! 1+ ; : init ] #0 ] ' none ,t ' exec ,t ' none ,t ' define ,t ] ' comp ,t ' none ,t ' *comp ,t ' post ,t ] ' *exec ,t ' none ,t ' none ,t ' none ,t ] ' var ,t ' none ,t ' none ,t ' none ,t ] drop ; [ init : 1eval ] @ dup #15 and lastc @ ] #4 shl over or lastc ! @tbl @ execute ; : eval ] over + : loop ] cmp ] ifl push dup push 1eval pop 1+ pop loop ; then 2drop ; ( interpreter ends here : block ] #256 * #0 sys #-128 + $40000 + + ; : load ] block #256 eval ; : thru ] 2dup #2 + or drop ] if push dup push load pop #2 + pop thru ; then drop ; Registers ┄───────┄ • RAX - tos • RSI - stack pointer • RDI - code heap pointer • R8 - internal vars - parked sp ◦ R8 +8 - parked hp ◦ R8 +16 - active dictionary ◦ R8 +24 - forth dictionary ◦ R8 +32 - macro dictionary ◦ RCX - temp • RDX - "a" register Dictionary ┄────────┄ 0, addr, word, addr, word, addr, word ↑ 0, addr, word, addr, word MDICT ↑ FDICT ↑ DICT Editor ┄────┄ • Modal - ispired by mix of vi and Chuck's • Word at a time entry • Color toggle, search • Clipboard is a stack! ? 1 2 3 4 5 6 7 8 9 0 - + BACK q w e r t y u i o p @ ! * a s d f g h j k l ; ' ENTER z x c v b n m , . / SPACE ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ✀ 🌈⚾🏳️🌈 % r ~ t [ y ( u : i ] o { p ( ░ ░ ░ ░ ░ ░🔴🔍← ↓ ↑ → ░ ░ ESC ░ ✀🗐⎘ ░⇇ ❏🔵⇉ ░ ESC Bootstrapping Font ┄────────────────┄ • 4x6 / 5x6 pixel characters • 4 x 6 + 1 (wide) = 25 bit characters • 48 character set █... 8 ..... 0 █... 8 █...█ 1 ███. e .█.█. a █..█ 9 ..█.. 4 █..█ 9 .█.█. a ███. e █...█ 1 $88e99e $101a4a1 Variables ┄───────┄ • Magenta Variables ~ foo ( #0 ◦ Place variable in the source block ◦ Makes moving things in editor break • Code Variables : foo [ here 0 , ] ; ◦ Places variables in a separate data heap ◦ Allows a resetable default No Loops, so far... ┄─────────────────┄ • Tail call can replace loops. • Chuck has endorsed this in some talks. • But his colorForth uses FOR..NEXT a good bit. : count ] ? if dup . 1- count ; then drop ; Flag Conditionals ┄───────────────┄ • HARD to get them to stick in your head • Sometimes nice when they leave the stack alone • But hard to compose several ] x @ 3 or drop if ( x isn't 3 ] then ] x @ ? if ( x is non-zero ] then ] x @ ? -if ( x is negate ] then ] x @ dup 3 or drop if ] dup 4 or drop if ( x isn't 3 or 4 ] then ] then drop ] x @ -3 + -if ( x-3 is negative, gotcha ] then ] x @ 3 cmp ifl ( x (signed) less than 3 ] then Graphics ┄──────┄ • Want to draw pretty pictures. • Want a better [ scalable ( font. • Lines, clipping, Bézier curves. ( basic box drawing : width [ here #1024 , ] ; : height [ here #768 , ] ; : color [ here 0 , ] ; : x [ here 0 , ] ; : y [ here 0 , ] ; : display ] $2400100 ; : row ] width @ * display + ; : at ] y ! x ! ; : +at ] y +! x +! ; : @at ] x @ y @ ; : hline ] push x @ y @ row + pop color @ fill ; : rbox ] ? if push dup hline #1 y +! pop 1- rbox ; then 2drop ; : box ] dup push rbox pop negate y +! ; : screen ] #0 #0 at width @ height @ box ; ( graphics stack implementation : gstack [ here #100 allot ] ; : gp [ here gstack , ] ; : gpush ] gp @ ! #1 gp +! ; : gpop ] #-1 gp +! gp @ @ ; : +grf ] x @ gpush y @ gpush color @ gpush ; : -grf ] gpop color ! gpop y ! gpop x ! ; Working with (x, y) values on the stack ┄─────────────────────────────────────┄ : rot ] push swap pop swap ; : -rot ] swap push swap pop ; : 2swap ] rot push rot pop ; : 2over ] push push 2dup pop pop 2swap ; : 4dup ] 2over 2over ; : 4drop ] 2drop 2drop ; : 2push ] pop -rot push push push ; : 2pop ] pop pop pop rot push ; : abs ] ? -if negate then ; Spans ┄───┄ • Simple, but flexible. • Keep a per-scanline list of on/off transitions. • "Mark" transitions per row. • "Stroke" in between marks, toggling on and off. • Allows line and curves to outline solids. • Implicitly do clipping by starting only inside viewpoint.. ................................................... ................................................... .....|................................|............ ....|................................|............. ...|..............|.....|......|................... ..|...............|.....|....|..................... ...|..............|.....|..|....................... ....|............||.....|.......................... .....|.......|....|.....|.......................... ......|...|.......|.....|.......................... .......|.|......................................... ........|.......................................... ................................................... ................................................... ................................................... ................................................... ................................................... .....|████████████████████████████████|............ ....|████████████████████████████████|............. ...|██████████████|.....|██████|................... ..|███████████████|.....|████|..................... ...|██████████████|.....|██|....................... ....|████████████||█████|.......................... .....|███████|....|█████|.......................... ......|███|.......|█████|.......................... .......|█|......................................... ........|.......................................... ................................................... ................................................... ................................................... ( curve drawing : rsize ] #20 ; : spans [ here height @ rsize * allot ] ; : 2sort ] 2dup min push max pop ; : rmark ] ? if push dup push @ 2sort @r ! pop 1+ pop 1- rmark ; then 2drop drop ; : mark ] ? -if 2drop ; then ] dup height @ negate + ? drop -if rsize * spans + rsize rmark ; then 2drop ; : rclear ] ? -if drop ; then 0 over mark width @ over mark 1- rclear ; : clear ] spans height @ rsize * #-1 #33 shr fill height @ rclear ; : ?inwidth ] ? -if 0 ? 2drop ; then ] dup width @ negate + ? drop -if ; then 0 ? 2drop ; : rstroke ] dup rsize * spans + 1+ rsize 2/ 1- : loop ] ? if push dup push @ ?inwidth if dup drop over at ] @r dup 1+ @ swap @ negate + #1 box then pop #2 + pop 1- loop ; then 2drop drop ; : stroke ] height @ : loop ] ? if 1- dup rstroke loop ; then drop ; Bézier Curves ┄───────────┄ • Polynomial curve in the plane. • Endpoints on the curve, control points form bounding polygon. • Affine transformation of endpoints, transforms curve equivalently. • Parametric subdivision is just interpolation. • 1/2 works out to use + and 2/ @bezier1.png: pels ] push #20 shl pop ; : /pels ] push #20 sar pop ; : ydiff ] nip negate + abs nip ; : average ] + 1+ 2/ ; : mid ] rot average push average pop ; : line ] 4dup ydiff 1- ? -if drop 4drop ; then ] 1- ? drop -if mid /pels mark ; then ] 4dup mid 2swap 2push 2dup 2push line 2pop 2pop line ; : lineto ] 2push @at pels 2pop 2dup at pels line ; : square ] dup * ; : vsub ] negate rot + push negate + pop ; : dist2 ] vsub /pels square swap square + ; : 'bezier ] 2swap 2push 4dup dist2 #-9 + ? drop ] -if 2pop 2drop line ; then ] 2pop 2swap 2dup 2push 2push 2dup 2pop mid ] 2dup 2push 2push 2push 2dup 2pop mid ] 2dup 2pop mid 2dup 2push 'bezier 2pop 2pop 2pop 'bezier ; : bezier ] 2push 2push @at pels 2pop pels 2pop 2dup at pels 'bezier ; Curve Editor ┄──────────┄ • Edit curves in source. • Store points in packed format. op * 2^20 + x * 2^10 + y • Use keyboard and mouse. What's Next? ┄──────────┄ • More Graphics • Use curve editor to create fonts. • Enhance graphics state to include scaling transforms. • More Stability • Consider catching stack faults? • Or wrap around stack? • Confront the pain points • Chuck's conditionals are tricky • 256 words per page is tight, maybe good? • Loops? • UEFI? • Get back to FPGA synthesizer? + visualize? DEMO + QUESTIONS❓ 🙏 Thank you!