--- /dev/null
+/bindings
+/history
+/6200-vddk.d/fedora.vmdk
+/6200-vddk.d/fedora.vmdk.xz
+/6200-vddk.d/fedora.vmdk.lck
+/6200-vddk.d/mp
+/6400-boot.d/qemu.sh
+/6400-boot.d/root
--- /dev/null
+#!/bin/bash -
+
+source functions
+
+# Title.
+export title="Tiny VMs"
+
+kernel="$(ls -1vr /boot/vmlinuz-* | head -1)"
+echo "qemu-kvm -display none -kernel $kernel -drive file=nbd:unix:\$unixsocket,snapshot=on -append 'console=ttyS0 root=/dev/sda1 rw' -serial stdio" > 6400-boot.d/qemu.sh
+chmod +x 6400-boot.d/qemu.sh
+
+# History.
+remember 'mkdir -p root/dev root/sbin root/bin root/usr/sbin root/usr/bin'
+remember 'sudo mknod root/dev/console c 5 1'
+remember 'cp /sbin/busybox root/sbin/'
+remember 'ln root/sbin/busybox root/bin/ls'
+remember 'ln root/sbin/busybox root/bin/sh'
+remember 'ln root/sbin/busybox root/bin/init'
+remember 'ls -lR root'
+remember "nbdkit -U - linuxdisk root --run 'export unixsocket; ./qemu.sh'"
+
+./restore
+pushd 6400-boot.d >/dev/null
+terminal
+popd >/dev/null
+./restore
--- /dev/null
+#!/bin/bash -
+
+xfce4-terminal --disable-server -x ./6600-next
--- /dev/null
+#!/bin/bash -
+
+source functions
+
+# Title.
+export title="Assemble!"
+
+# History.
+remember 'less assemble.sh'
+remember 'emacs -nw hello.asm'
+remember "nbdkit sh assemble.sh file=hello.asm --run 'qemu-system-i386 -hda \$nbd'"
+remember 'less pyrit.asm'
+remember "nbdkit sh assemble.sh file=pyrit.asm --run 'qemu-system-i386 -hda \$nbd'"
+
+banner "Demo Credit: Pyrit by Jan Kadlec (Řrřola) "
+banner "https://www.pouet.net/prod.php?which=78045"
+echo
+
+terminal
--- /dev/null
+#!/bin/bash -
+
+source functions
+
+# Title.
+export title="Reflection"
+
+# History.
+remember 'nbdkit info base64exportname'
+
+for program in 'uBMAzRD8uACgjtiOwLQEo5D8McC5SH4x//OriwVAQKuIxJK4AByruJjmq7goFLsQJbELq4PAFpOr/sST4vUFjhWA/1x167+g1LEFuAQL6IUBg8c84vW+lvyAfAIgci3+xYD9N3SsrZetPCh0CzwgdQTGRP4o6F4Bgf5y/XXbiPAsAnLSNAGIwojG68qAdAIIRYPlB1JWVXUOtADNGjsWjPx09okWjPy+gPy5BACtPUABl3JD6BcBge9CAYoFLCByKVZXtAT25AHGrZfGBCC4CA7oAgFfXusfrQnAdC09APCXcxTo6ACBxz4BuAwMiXz+gL1AAQt1BTHAiUT+gD0cdQbHBpL8OAroxgDizL6S/K0IwHQMBAh1CLQc/g6R/HhKiUT+izzorgB1LrQCzRaoBHQCT0+oCHQCR0eoA3QNgz6A/AB1Bo1FCKOA/Jc9/uV0Bz0y53QCiQRdXlqLBID6AXYKBYACPYDUchvNIEhIcgODwARQ0eixoPbx/syA/JRYcgOAzhaJBAUGD5O5AwDkQDz8cg2/gvyDPQB0A6/i+Ikd6cL+GBg8JDx+/yQAgEIYEEiCAQC9234kPGbDADxa/6U8ZmYAAAAAAAAAAHICMcCJhUABq8NRV5xQu6R9LteTuQoA+Ij4iPzo4f/Q4+L1gcdsAlhAqAd14J1fWcNPVao=' \
+'Dg4OHwcX/L8Af7ANuSBO86q8AP+4EXxQMcCjfn6wPuhQAegEAQnAdA7oPQGX86TD6G0ACcB0WejSAIA8DXRRv8N9igVHJf8AdBORVvOmdQZY6LgA/yUBz0dHXuvl6KUAUKw8PXQ0vm586CYB66NAIyENMcBQ6PEAloA8DXQLWFDokQCs6CcBdfpYQD3oA3Xkw+hxAFCwP+jYAOgDAF+rw+gcAIA8LXQOgDwrdeNQ6A0AWQHI6+1Q6AQA99jr80boHwCAPC90DoA8KnXEUOgQAFn36evtUOgHAFmRmff56+JG6CgArDwodQvotP+APCl0IOly/zxAcwZO6C0A6w7oBQCTiwfDrCQfAMC0foA8IHUtRuv4MdK5CgD38QnAUnQD6PH/WAQw6YUAMdusLDA8CpiTcwm5CgD34QHD6+5Ow80g6Fz/uTHA6B8Agz5+fgB0BKN+fsNQXoPAFKN+fujX/qF+fj0gzXXtw7kUAPfhBQB/w+g5AL6AflZf6C0AqjwIdQJPTzwNdfLDrDwNdCQ8InULrDwidA3oFAB19sNO6P/+6HD/rDw7dQnDtADNFjwNdQewCugCALANtA67BwDNEDwNwwNuZXcAfARsaXN0cnwDcnVuRX0FcHJpbnSJfQVpbnB1dJF8AmlmMHwEZ290b0F9BnN5c3RlbT99AE9PVao=' \
+'uBMAzRD8uACgjtiOwL7Bfb8gFC6tkbvwANHhuBg3cwO4OALoIgAB34PrEHJP6BgAKd+D7wjr4q2XrYTkk7AwUMZE/wLorgBYUFNRV1C7eX0u15O5CACI+NDjcgIxwID/EHIHgD0OdJgyBari6YHHOAFYQKgHddVfWVtYw4HHiAmB/ut9dY2xBbgCAC6lq+L7tADNGjsWBPp09okWBPq0Ac0WtAB0As0WiOA8AXUCzSAsSHIMPAlzCLv1fS7Xov75viDmrZetkzHA6CsAgDb/+YC4KA54B6Ai5rED0uDoaP+9N3y3If/Vty7/1bco/9W3NP/V65t0A+hO/4n4MdK5QAH38YjUCMSA5Ad1WrU3OG3/EOQ4rQAKEOQ4bQgQ5DitwP4Q5IT/dCv2wwV0DDsWAPqwAnIMsAjrCDwAsARyArABhMR1I4jYhMR1HdDodfiwCOv0iRYA+i6iOn2g/vmExHUGINx0GojYiET+qAW7gP11A7sCAKgMdAL32wHfiXz8wwBC5+f//348PH788PD8fjz//////////zx+///n50IAPH7/////fjw8ftvb////pQAAABgYAAAAPH4/Dw8/fjwAAP5/AkICQv9/QEJ+fgICfwLAA0ACfwJAAv5/AkL/e0AKfn4CQP9/AACYqpBQmGSgPKhQAQAACAACAAAEVao='
+do
+ remember "qemu-system-i386 -drive snapshot=on,file.driver=nbd,file.host=localhost,file.port=10809,file.export=$program"
+done
+
+banner "Demo Credit: Oscar Toledo Gutierrez"
+banner "https://github.com/nanochess "
+echo
+
+terminal
--- /dev/null
+#!/bin/bash -
+
+xfce4-terminal --disable-server -x ./6800-next
--- /dev/null
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" href="style.css" type="text/css"/>
+<script src="code.js" type="text/javascript"></script>
+
+<h1>What did we learn?</h1>
+
--- /dev/null
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" href="style.css" type="text/css"/>
+<script src="code.js" type="text/javascript"></script>
+
+<h1>What did we learn?</h1>
+
+<ul>
+<li> 512 bytes ought to be enough for anybody
+</ul>
--- /dev/null
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" href="style.css" type="text/css"/>
+<script src="code.js" type="text/javascript"></script>
+
+<h1>What did we learn?</h1>
+
+<ul>
+<li> 512 bytes ought to be enough for anybody
+<li> Any problem can be solved with a little bit more shell script
+</ul>
--- /dev/null
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" href="style.css" type="text/css"/>
+<script src="code.js" type="text/javascript"></script>
+
+<h1>What did we learn?</h1>
+
+<ul>
+<li> 512 bytes ought to be enough for anybody
+<li> Any problem can be solved with a little bit more shell script
+<li> <code>qemu -hda</code> is a vitally important option
+ that must never be removed
+</ul>
--- /dev/null
+#!/bin/bash -
+
+f=$tmpdir/source.asm
+s=$tmpdir/final.asm
+b=$tmpdir/binary
+
+case "$1" in
+ config)
+ if [ "$2" = "file" ]; then
+ ln -sf "$(realpath "$3")" $f
+ else
+ echo "unknown parameter $2=$2" >&2
+ exit 1
+ fi ;;
+ config_complete)
+ echo 'org 07c00h' > $s
+ cat $f >> $s
+ echo 'times 510-($-$$) db 0' >> $s
+ echo 'db 055h,0aah' >> $s
+ nasm -f bin $s -o $b ;;
+ get_size) echo 512 ;;
+ pread) dd if=$b skip=$4 count=$3 iflag=count_bytes,skip_bytes ;;
+ can_write) ;;
+ pwrite) exit 1 ;;
+ *) exit 2 ;;
+esac
--- /dev/null
+# -*- shell-script -*-
+
+# Colour ls.
+if [ -f /etc/profile.d/colorls.sh ]; then . /etc/profile.d/colorls.sh; fi
+
+# Fancy prompt colours (see
+# https://wiki.archlinux.org/index.php/Color_Bash_Prompt)
+titlecol=$'\e[1;37;41m' ;# colour for the title
+promptcol=$'\e[0;32m' ;# colour for the prompt
+commandcol=$'\e[1;31m' ;# colour for the typed command
+outputcol=$'\e[0m' ;# colour for command output
+
+export PS1="\n\[$promptcol\]\$ \[$commandcol\]"
+
+trap 'echo -ne "$outputcol"' DEBUG
+
+# Load key bindings (if any).
+bind -f $talkdir/bindings
+
+# Same as the banner function, but we cannot reuse it.
+printf "%s %s %s\\n" $titlecol "$title" $outputcol
--- /dev/null
+function plugins ()
+{
+ document.write ("\
+<div class=\"plugins\"> \
+<p id=\"caption\">plugins available in nbdkit 1.15.6</p> \
+<ul> \
+<li id=\"plugin-curl\"> curl \
+<li id=\"plugin-data\"> data \
+<li id=\"plugin-ext2\"> ext2 \
+<li id=\"plugin-file\"> file \
+<li id=\"plugin-floppy\"> floppy \
+<li id=\"plugin-full\"> full \
+<li id=\"plugin-guestfs\"> guestfs \
+<li id=\"plugin-gzip\"> gzip \
+<li id=\"plugin-info\"> info \
+<li id=\"plugin-iso\"> iso \
+<li id=\"plugin-libvirt\"> libvirt \
+<li id=\"plugin-linuxdisk\"> linuxdisk \
+<li id=\"plugin-lua\"> lua \
+<li id=\"plugin-memory\"> memory \
+<li id=\"plugin-nbd\"> nbd \
+<li id=\"plugin-null\"> null \
+<li id=\"plugin-ocaml\"> ocaml \
+<li id=\"plugin-partitioning\"> partitioning \
+<li id=\"plugin-pattern\"> pattern \
+<li id=\"plugin-perl\"> perl \
+<li id=\"plugin-python\"> python \
+<li id=\"plugin-random\"> random \
+<li id=\"plugin-ruby\"> ruby \
+<li id=\"plugin-rust\"> rust \
+<li id=\"plugin-sh\"> sh \
+<li id=\"plugin-split\"> split \
+<li id=\"plugin-streaming\"> streaming \
+<li id=\"plugin-tar\"> tar \
+<li id=\"plugin-tcl\"> tcl \
+<li id=\"plugin-vddk\"> vddk \
+<li id=\"plugin-zero\"> zero \
+</ul> \
+</div> \
+");
+}
+
+function filters (layer)
+{
+ document.write ("\
+<div class=\"filters\"> \
+<p class=\"filtercaption\">filters available in nbdkit 1.15.6</p> \
+<ul> \
+<li id=\"filter" + layer + "-blocksize\"> blocksize \
+<li id=\"filter" + layer + "-cache\"> cache \
+<li id=\"filter" + layer + "-cacheextents\"> cacheextents \
+<li id=\"filter" + layer + "-cow\"> cow \
+<li id=\"filter" + layer + "-delay\"> delay \
+<li id=\"filter" + layer + "-error\"> error \
+<li id=\"filter" + layer + "-fua\"> fua \
+<li id=\"filter" + layer + "-log\"> log \
+<li id=\"filter" + layer + "-nocache\"> nocache \
+<li id=\"filter" + layer + "-noextents\"> noextents \
+<li id=\"filter" + layer + "-noparallel\"> noparallel \
+<li id=\"filter" + layer + "-nozero\"> nozero \
+<li id=\"filter" + layer + "-offset\"> offset \
+<li id=\"filter" + layer + "-partition\"> partition \
+<li id=\"filter" + layer + "-rate\"> rate \
+<li id=\"filter" + layer + "-readahead\"> readahead \
+<li id=\"filter" + layer + "-retry\"> retry \
+<li id=\"filter" + layer + "-stats\"> stats \
+<li id=\"filter" + layer + "-truncate\"> truncate \
+<li id=\"filter" + layer + "-xz\"> xz \
+</ul> \
+</div> \
+");
+}
--- /dev/null
+# -*- shell-script -*-
+# This creates some standard functions. See also $talkdir/bashrc
+# which runs in the same bash context as the terminal.
+
+# Place any local environment variables and settings in "local".
+if [ -f local ]; then source local; fi
+
+# Environment variables.
+export HISTFILE=$talkdir/history
+export PATH=$talkdir:$PATH
+export EDITOR="emacs -nw"
+
+# remember <command> <args ...>
+#
+# This function does two things: (1) It adds the command and arguments
+# to the shell history, so that commands can be recalled using up
+# arrow or reverse search. (2) It makes a function key recall the
+# command. The first command is assigned to F2, the second to F3 and
+# so forth.
+
+rm -f $HISTFILE
+touch $HISTFILE
+rm -f $talkdir/bindings
+touch bindings
+
+fnum=2
+keys=(- OP OQ OR OS '[15~' '[17~' '[18~' '[19~' '[20~' '[21~')
+
+remember ()
+{
+ echo "$@" >> $HISTFILE
+ echo "$@" | sed -e 's/"/\\"/g; s/$/"/' \
+ -e 's/^/"\\e'"${keys[$fnum]}"'":"\\C-k \\C-u/' >> $talkdir/bindings
+ ((fnum++))
+}
+
+terminal ()
+{
+ chmod -w $HISTFILE
+ /bin/bash --rcfile $talkdir/bashrc "$@"
+}
+
+banner ()
+{
+ printf "%s %s %s\\n" $'\e[1;37;41m' "$1" $'\e[0m'
+}
--- /dev/null
+ mov ah,0 ; clear screen
+ mov al,3
+ int 0x10
+ mov ah,0x13 ; print string
+ mov bl,0xa
+ mov al,1
+ mov cx,len
+ mov dh,0
+ mov dl,0
+ mov bp,hello
+ int 0x10
+ hlt
+hello: db "*** Hello KVM Forum ***",0xd,0xa
+len: equ $-hello
--- /dev/null
+; Pyrit
+
+; a 256-byte intro by Rrrola <rrrola@gmail.com>
+
+; greets to everyone who's computer is too fast :)
+
+; This is loosely based on my intro 'Gem' (shown on Demobit),
+; but the code is much better.
+
+; Vector3: X right, Y down, Z forward.
+; On the FP stack it looks like {Y X Z} (Y is often used in comparisons).
+; In memory it looks like {Z X Y}, which saves a displacement byte.
+; (u'v) is the dot product: ux*vx + uy*vy + uz*vz.
+
+ xor ax,ax
+ xor bx,bx
+ mov cx,0ffh
+ mov di,-2
+; mov ss,dx
+ mov sp,di
+ mov si,100h
+ mov bp,091ch
+
+; assume al=0 bx=0 sp=di=-2 si=0100h bp=09??h
+
+;Set video mode and earth+sky palette
+ dec di ; u16[100h] = -20401, u16[10Ch] = -30515
+ mov al,13h
+ dec di ; initial pixel_adr@di = -4
+
+P:shr cl,1 ; B@cl = 0..8..31,31..0
+
+ int 10h ; set video mode / color: bx=index dh=R ch=G cl=B
+
+ movsx cx,bl ; 0..127,128..255 (palette index)
+ xor ch,cl ; 0..127,127..0
+ mov cl,ch
+ mov ax,cx
+ mul ax ; R@dh = 0..16..63,63..16..0
+
+ shr cx,1 ; G@ch = 0..63,63..0
+
+ inc bl ; keep default color 0
+ js Q ; R@dh = 0..63,63..16..0
+ xchg cl,dh ; B@cl = 0..16..63,63..0
+Q:mov ax,1010h
+ jnz P ;bx=0 cx=0
+
+ ; Constants expected at a fixed address below.
+ mov ax,0b04fh
+ mov word[100h],ax
+ mov ax,04f13h
+ mov word[102h],ax
+ mov ax,0e9d0h
+ mov word[104h],ax
+ mov ax,010cdh
+ mov word[106h],ax
+ mov ax,0be0fh
+ mov word[108h],ax
+ mov ax,030cbh
+ mov word[10ah],ax
+ mov ax,088cdh
+ mov word[10ch],ax
+ mov ax,089e9h
+ mov word[10eh],ax
+
+;Each frame: Generate normals to p0..p11=[bp+200h,300h,...].
+M:mov ax,0x4731 ; highest 9 bits: float32 exponent 1/256 (for T)
+ ; lower byte = 2*number of rotations+1
+ ; lowest 4 bits must be 0x1 for 'test cl,al'
+ mov dx,0xA000-10-20-20-4
+ mov es,dx ; dx:bx = YX:XX = 0x9fca:0
+ pusha ; adr: -18 -16 -14 -12 -10 -8 -6 -4 -2
+ ; stack: di si bp sp bx dx cx ax 0
+ ; data: -4 100 9?? -2 0 9fca {T/256}
+ mov cx,12
+G:add bp,si ; i@cx = 12...1; bp points to p[12-i]; carry=0
+ pusha
+
+;Generate 12 planes with unit normals.
+
+; fld1 ; platonic dodecahedron: exact is atan((1+sqrt5)/2)=1.017rad
+ fld dword[di-2] ;|t=T/256: morphing shape: cube, platonic12, rhombic12
+
+ fsincos
+
+ fldz ;|a=0 b c (a*a+b*b+c*c = 1)
+; fldlg2 ;irregular shape
+
+N:test cl,al ;=1 ;|a b c
+ jnz K
+ fchs
+K:fstp st3 ;|b c +-a (scramble so that all 12 planes are generated)
+ loop N ;cl=0 ;|z x y
+
+;Do a bunch of slow rotations. z x y -> cx-sy cy+sx z
+
+R:fstp st3 ;|x y z
+Z:fld st1 ;|y x y z ;|x sy x cy z
+ fld dword[di-2] ;|t=T/256
+ fsincos ;|c=cos(t) s=sin(t) y x y z ;|c s x sy x cy z
+ fmulp st4 ;|s y x cy z ;|s x sy cx cy z
+ fmulp ;|sy x cy z ;|sx sy cx cy z
+ add al,0x7F ; loop 2x
+ jo Z
+ faddp st3 ;|sy cx cy+sx z
+ fsubp ;|new.z=cx-sy .x=cy+sx .y=z
+ jc R ; loop 24x
+
+S:fstp dword[bp+si] ;[bp+100]=.z [bp+104]=.x [bp+108]=.y
+ sub si,di
+ jpo S
+
+ popa
+ loop G
+ popa
+
+; the visible pixels are A0000..AF9FF, I want X=0 Y=0 in the center
+;Each pixel: cx=T dx:bx=YX:XX(init=9fca:0) di=adr(init=-4)
+X:inc dx ; part of "dx:bx += 0x0000CCCD"
+X2:
+ stosb
+
+ pusha ; adr: -18 -16 -14 -12 -10 -8 -6 -4 -2
+ fninit ; stack: di si bp sp bx dx cx ax 0
+ mov bx,es ; s16: pixadr 100 9?? -2 ..X..Y T result
+ mov di,-4 ;di = address of pushed ax
+
+;Compute ray direction.
+ fild word[BIG] ; store 28799 as a double, read as two floats
+ fst qword[bx] ; t_front@float[bx] = 0, t_back@float[bx+4] = 6.879
+ fild word[di+4-9]
+ fild word[di+4-8] ;|y=Y x=X z=BIG
+
+;Intersect the pyrite.
+ call GEM
+ popa ; color -> pushed ax
+; mov al,dl ; show only palette
+
+;; Faster, but lower quality: draw each pixel twice.
+; stosb
+; add bx,0xCCCD; dx:bx = YXX += 0000CCCD
+; adc dx,0
+
+ add bx,0xCCCD; dx:bx = YXX += 0000CCCD
+ jnc X2
+ jnz X ; do 65536 pixels
+
+ in al,60h
+ dec ax ; ah=0 (checkboard uses positive color indices)
+ loopnz M ; T--
+; ret ; fallthrough
+
+GEM:
+;Hit the pyrite.
+ xchg ax,cx ; ax = T
+
+; Faster (+4 or +8 bytes): test the shape only in the center of the screen
+ add dh,dh
+ jo B
+ add dl,dl
+ jo B
+
+;Ray-plane intersection.
+;Find the front plane with maximum t and back plane with minimum t.
+; tf@[bx], tb@[bx+4] ray parameter t
+; pf@[bx+si], pb@[bx+4+si] pointer to plane
+ mov cx,12 ; i@cx = 12...1
+I:add bp,si ; bp points to p[i]
+ fldlg2 ;|pd=0.301 y x z
+ fadd dword[bp+si] ;|N=pd-(ro'p[i]) y x z ; ro = 0 0 -1
+
+ push si ; Dot product:
+D:fld dword[bp+si] ;|p[i].z ...
+ fmul st4 ;|rd.z*p[i].z ...
+ sub si,di ; 100 104 108
+ jpo D ;|(rd*p[i]).y .x .z N rd.y .x .z
+ pop si
+ faddp
+ faddp ;|D=(rd'p[i]) N y x z
+
+;If we hit the plane from the front (D<0), update tf. Otherwise update tb.
+ push bx
+ fst dword[bp+di]; -> p[i].dot_rd (will be read later)
+ test [bp+di+2],sp ; sf=1 if we're in front of the plane
+ js FRONT
+ sub bx,di ; bx = address of tf?tb
+FRONT: ; D<0: if tf*D < N { tf=N/D; pf=current; } maximalize tf
+ fld st0 ; D>=0: if tb*D < N { tb=N/D; pb=current; } minimalize tb
+ fmul dword[bx] ;|(tf?tb)*D D N y x z
+
+;;DosBOX-compatible FPU comparison, +5 bytes (+3 but we need ax)
+; push ax
+; fcomp st2 ;|D N y x z
+; fnstsw ax
+; sahf ; cf = (tf?tb)*D < N
+; pop ax
+; jc NEXT
+
+ fcomip st2
+ jc NEXT
+
+;another alternative, +6 bytes
+; fsub st2
+; fstp dword[bp-8]
+; test [bp-6],sp ; sf=1 if <0
+; js NEXT
+
+
+ fdivr st1 ;|t=N/D N y x z
+ fst dword[bx] ; -> tf?tb
+ mov [bx+si],bp ; pf?pb = current
+NEXT:
+ fcompp
+ pop bx ;|y x z
+
+ mov dx,[bx+6]
+ cmp dx,[bx+2] ; if tf>tb { no_hit: early exit }
+ jng B ;si=100 ;|y x z
+
+ loop I
+
+;Reflect: reflect(i,n) = i - 2*n*(i'n)
+ mov bx,[bx+si] ; pf
+Y:fld dword[bx+di] ;|(rd'pf) rd.y .x .z ; reads pf->dot_rd
+ fmul dword[bx+si] ;|(rd'pf)*pf.z rd.y .x .z
+ fadd st0 ;|2*(rd'pf)*pf.z rd.y .x .z
+ fsubr st3 ;|R.z=rd.z-2*(rd'pf)*pf.z rd.y .x .z
+ sub si,di ;100 104 108
+ jpo Y ;si=10C ;|(R=i-2*n(i'n)).y R.x R.z rd.y .x .z
+
+;Environment map: chessboard below, sky gradient above.
+B:
+; Subtle highlight on the pyrite.
+ fld st0
+ fimul word[C] ; 16993 (background) or 20036 (pyrit)
+ fistp dword[di] ;|y x z
+ sar dword[di],22 ; if y>=-0.5 { chessboard } else { sky }
+ js E ; the sky is just y (= y^2 after gamma)
+
+; Everything the same brightness. (-6 bytes)
+; fist word[di] ;|y x z
+; sar word[di],8 ; if y>=-0.5 { chessboard } else { sky }
+; js E ; the sky is just y (= y^2 after gamma)
+
+; Dark background version.
+; fist word[di] ;|y x z
+; shld cx,si,16-3
+; xor cl,9 ; hit?8:9 - make the background darker
+; sar word[di],cl ; if y>=-0.5 { chessboard } else { sky }
+; js E ; the sky is just y (= y^2 after gamma)
+
+ fidivr word[si] ;|C/y x z (C = hit?-30515:-20401)
+ fmul st1,st0
+ fmul st2 ;|u=z*C/y v=x*C/y z
+
+ fistp dword[bp+di]
+ sub al,[bp+di+1]
+ fistp dword[bp+di]
+ xor al,[bp+di+1] ; xortex@ax = (T-u) XOR v
+
+; aam -32-24 ; more interesting floor texture
+ and al,9<<3
+ add al,10<<3 ; tex = (xortex AND 0b1001) + 10 [10|11|18|19]
+ mul byte[di]
+ mov [di],ah ; pushed al = tex*y
+
+E:ret
+
+BIG dw 28799
+C dw 16993
+C2 dw 20036
--- /dev/null
+#!/bin/bash -
+
+# Safety-valve for unwary users...
+if [ "$LOGNAME" != "rjones" ] && [ "$LOGNAME" != "eblake" ]; then
+ exit 1
+fi
+
+if [ "$talkdir" = "" ]; then exit 1; fi
+
+fusermount -u $talkdir/6200-vddk.d/mp >& /dev/null
+
+if [ -d "$talkdir/6400-boot.d/root" ]; then
+ sudo rm -rf $talkdir/6400-boot.d/root
+fi
+
+sleep 0.5; killall nbdkit >& /dev/null
+
+exit 0
--- /dev/null
+#!/bin/bash -
+# Run the talk.
+
+set -e
+
+# Avoid GNOME keyring stupidity
+export GNOME_KEYRING_CONTROL=
+export GNOME_KEYRING_PID=
+
+# No proxy.
+#unset http_proxy
+#unset https_proxy
+#unset ftp_proxy
+
+# Clean up after previous run.
+talkdir=$PWD ./restore
+
+# Precreate any files necessary.
+#(nothing)
+
+# Run techtalk. The demos require nbdkit 1.15.6, libnbd 1.1.5, and qemu 4.2,
+# which are not present in Fedora 30, so point to self-built versions.
+export PATH=$HOME/d/nbdkit:$HOME/d/qemu:$PATH
+$HOME/d/libnbd/run techtalk-pse
+#~/d/techtalk-pse/techtalk-pse
--- /dev/null
+/* Red Hat red is rgb(238,0,0). */
+
+body {
+ background: url(redhat.png) no-repeat;
+ background-position: 98% 6px;
+ background-size: auto 48px;
+ /* font-size: 28pt; */ /* For max */
+ font-size: 20pt; /* For 1024x768 */
+ font-family: Red Hat Text, liberation, helvetica;
+ /* font-family: helvetica; */
+
+ /* Can be used to scale the whole document. */
+ /*transform: translate(-10%,-10%) scale(0.75,0.75);*/
+}
+
+body td, body th { /* why?? */
+ font-size: 24pt;
+ padding-bottom: 8px;
+}
+
+h1 {
+ color: rgb(238,0,0);
+ /*font-size: 48px;*/
+ font-size: 40px;
+ top: 8;
+ left: 0;
+ border-bottom: 2px solid rgb(238,0,0);
+}
+
+h2 {
+ color: rgb(238,0,0);
+ font-size: 32px;
+ font-style: italic;
+ border-bottom: 2px solid rgb(238,0,0);
+}
+
+b {
+ color: rgb(238,0,0);
+}
+
+/* Title page. */
+div#titlepage {
+ margin-top: 100px;
+ width: 80%;
+ margin-left: 10%;
+}
+
+div#titlepage p.title {
+ color: rgb(238,0,0);
+ font-weight: bold;
+ font-size: 48px;
+ text-align: left;
+}
+
+div#titlepage p.author {
+ font-size: 36px;
+ text-align: left;
+}
+
+div#titlepage p.abstract {
+ font-size: 28px;
+ text-align: left;
+}
+
+/* Code */
+pre.code {
+ margin-left: 1em;
+ background: #eee;
+}
+
+code {
+ color: rgb(238,0,0);
+}
+
+/* Bullet points */
+li {
+ padding-bottom: 16px;
+}
+
+/* Plugins box. */
+div.plugins {
+ background: #f8f8ff;
+ border: 1px solid rgb(238,0,0);
+ border-radius: 15px;
+ margin-left: auto;
+ margin-right: auto;
+ width: 800px;
+ height: 400px;
+ /* Position relative is needed so that items may be
+ positioned inside. */
+ position: relative;
+}
+
+div.plugins p#caption {
+ position: absolute;
+ bottom: -5px; right: 5px;
+ color: rgb(238,0,0);
+ text-align: right;
+ font-size: 16px;
+ font-weight: bold;
+}
+
+div.plugins ul {
+ position: absolute;
+ top: 10%;
+ width: 700px;
+ height: 380px;
+ column-count: 4;
+ list-style-type: none;
+ margin: 0;
+}
+
+div.plugins ul li {
+ padding: 0px;
+ margin: 5px;
+}
+
+div.plugins ul li.highlighted {
+ border: 1px solid rgb(238,0,0);
+ background: #fff;
+ padding-left: 10px;
+ color: rgb(238,0,0);
+ border-radius: 20px;
+ font-weight: bold;
+}
+
+/* Filters box. */
+div.filters {
+ background: #f8fff8;
+ border: 1px solid rgb(238,0,0);
+ border-radius: 15px;
+ margin-left: auto;
+ margin-right: auto;
+ width: 800px;
+ height: 280px;
+ /* Position relative is needed so that items may be
+ positioned inside. */
+ position: relative;
+}
+
+div.filters p.filtercaption {
+ position: absolute;
+ bottom: -5px; right: 5px;
+ color: rgb(238,0,0);
+ text-align: right;
+ font-size: 16px;
+ font-weight: bold;
+}
+
+div.filters ul {
+ position: absolute;
+ top: 10%;
+ width: 700px;
+ height: 260px;
+ column-count: 4;
+ list-style-type: none;
+ margin: 0;
+}
+
+div.filters ul li {
+ padding: 0px;
+ margin: 5px;
+}
+
+div.filters ul li.highlighted {
+ border: 1px solid rgb(238,0,0);
+ background: #fff;
+ padding-left: 10px;
+ color: rgb(238,0,0);
+ border-radius: 20px;
+ font-weight: bold;
+}
+
+/* Colored highlighting */
+div.plugins ul li.bg_r,
+div.filters ul li.bg_r {
+ background: #b00;
+ color: white;
+}
+
+div.plugins ul li.bg_g,
+div.filters ul li.bg_g {
+ background: #0b0;
+ color: white;
+}
+
+div.plugins ul li.bg_b,
+div.filters ul li.bg_b {
+ background: #00b;
+ color: white;
+}
+
+/* For images which must be centered on the page. */
+div.allcenter {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 50vw;
+}
+
+div.all-center img {
+}
+
+/* Outlined text. */
+.outline {
+ text-shadow: 2px 2px 0 rgb(238,0,0),
+ -2px 2px 0 rgb(238,0,0),
+ 2px -2px 0 rgb(238,0,0),
+ -2px -2px 0 rgb(238,0,0),
+ 0px 2px 0 rgb(238,0,0),
+ 0px -2px 0 rgb(238,0,0),
+ -2px 0px 0 rgb(238,0,0),
+ 2px 0px 0 rgb(238,0,0),
+ 4px 4px 0 rgb(238,0,0),
+ -4px 4px 0 rgb(238,0,0),
+ 4px -4px 0 rgb(238,0,0),
+ -4px -4px 0 rgb(238,0,0),
+
+ 0px 4px 0 rgb(238,0,0),
+ 0px -4px 0 rgb(238,0,0),
+ -4px 0px 0 rgb(238,0,0),
+ 4px 0px 0 rgb(238,0,0),
+ 2px 4px 0 rgb(238,0,0),
+ -2px 4px 0 rgb(238,0,0),
+ 2px -4px 0 rgb(238,0,0),
+ -2px -4px 0 rgb(238,0,0),
+ 4px 2px 0 rgb(238,0,0),
+ -4px 2px 0 rgb(238,0,0),
+ 4px -2px 0 rgb(238,0,0),
+ -4px -2px 0 rgb(238,0,0),
+
+ 4px 4px 0 rgb(255,128,128),
+ -4px 4px 0 rgb(255,128,128),
+ 4px -4px 0 rgb(255,128,128),
+ -4px -4px 0 rgb(255,128,128),
+ 0px 4px 0 rgb(255,128,128),
+ 0px -4px 0 rgb(255,128,128),
+ -4px 0px 0 rgb(255,128,128),
+ 4px 0px 0 rgb(255,128,128),
+ 8px 8px 0 rgb(255,128,128),
+ -8px 8px 0 rgb(255,128,128),
+ 8px -8px 0 rgb(255,128,128),
+ -8px -8px 0 rgb(255,128,128),
+
+ 0px 8px 0 rgb(255,128,128),
+ 0px -8px 0 rgb(255,128,128),
+ -8px 0px 0 rgb(255,128,128),
+ 8px 0px 0 rgb(255,128,128),
+ 4px 8px 0 rgb(255,128,128),
+ -4px 8px 0 rgb(255,128,128),
+ 4px -8px 0 rgb(255,128,128),
+ -4px -8px 0 rgb(255,128,128),
+ 8px 4px 0 rgb(255,128,128),
+ -8px 4px 0 rgb(255,128,128),
+ 8px -4px 0 rgb(255,128,128),
+ -8px -4px 0 rgb(255,128,128);
+}
+
+/* Warning symbol. */
+span.warning {
+ background-color: yellow;
+ font-weight: bold;
+}
+
+/* Attribution for artwork etc. */
+p.attribution {
+ position: absolute;
+ right: 10px;
+ bottom: 10px;
+ text-align: right;
+ font-size: 10pt;
+}