:asm tnd! ( b -- ) POP AX OUT 0xc0 # AL NEXT :asm tnd-vol! ( vol chan -- ) POP AX MOV CL 5 # SHL AX CL POP CX OR AL CL OR AL 0x90 # OUT 0xc0 # AL NEXT :asm tnd-note! ( note chan -- ) POP DX MOV CL 5 # SHL DX CL ( DL: channel mask ) POP BX ( BX: note ) ( first command ) MOV AL 0x0f # AND AL BL ( low 4 bits of divisor ) OR AL DL ( channel mask ) OR AL 0x80 # ( update frequency ) OUT 0xc0 # AL ( second command ) MOV AX BX DEC CL ( shift by 4 ) SHR AX CL AND AL 0x3f # ( wrap any divisor above 10 bits ) OUT 0xc0 # AL NEXT :asm freq>tnd ( f -- d ) MOV AX 0x9E99 # MOV DX 0x36 # POP BX DIV BX MOV CL 5 # SHR AX CL PUSH AX NEXT : tnd-silence 0xf 0 tnd-vol! 0xf 1 tnd-vol! ; : tnd-2chord ( f1 f2 count -- ) >rot freq>tnd 0 tnd-note! freq>tnd 1 tnd-note! 0 0 tnd-vol! 0 1 tnd-vol! sleep-csec tnd-silence ; : set-tandy ( f -- ) if ' tnd-2chord else ' spk-arp then ' arp redefine ; : detect-tandy 0xc000 0xf000 b@far 0x21 = 0xfffe 0xf000 b@far 0xfd = or ; ' init :chain detect-tandy set-tandy ;