diff --git a/src/alan/chat.112 b/src/alan/chat.112 new file mode 100644 index 00000000..d2a4a429 --- /dev/null +++ b/src/alan/chat.112 @@ -0,0 +1,581 @@ +;;;-*-Midas-*- + +title Chat -- User. + +.insrt chat format +if2, ffpage==:com"page+com"npages ;First free page. + +a=:1 +b=:2 +c=:3 +d=:4 +e=:5 + +t=:6 ? intacs==:t_6+3 ;T, TT & X saved by interrupts. +tt=:7 +x=:10 + +pi=:15 ;PI=I-1 So JFFO will load I +i=:16 ;Bit numbers kept here. +u=:17 ;Keep our UIND here at all times! + +dsk==:1 +usr==:2 +ttyo==:3 +ttyi==:4 + +stop=:.break 16,100000 +quit=:.logout 1, +tyo=:.iot ttyo, +tyi=:.iot ttyi, + +;;;Flags in 0 +%f==:0,,525252 +%fsail==:1_17. ;User's terminal has SAIL characters. +%ffull==:1_16. ;User's keyboard can generate the full character set. +%fmeta==:1_15. ;User's keyboard has a Meta key. +%faty==:1_14. ;The TTY has been returned to us, but the user hasn't typed + ;any characters since then. + +;;;Pre-allocated bits in our UHANG word. +%b==:525252,,525252 +%bcmd==:1_0 ;Wakeup from CMDBUF. +%brip==:1_1 ;Demon job vanished. +%baty==:1_2 ;The TTY has been returned to us and the user has typed a + ;character, so the screen needs to be repainted. +nbits==:33. ;Free + +define syscall name,args + .call [setz ? sixbit /name/ ? args(400000)] +termin + +define lose code,pc + jrst [ syscall lose,[movei code ? movei pc] + .lose %lssys] +termin + +define princ &string& + move t,[440700,,[ascii string]] + movei tt,.length string + .call sout + .lose %lssys +termin + +.scalar height ;Height of the screen. +.scalar width ;Width of the screen. + +define def name,size=1 +name==:.val. +.val.==.val.+ +termin + +.scalar aline ;First line on the screen. +.scalar zline ;Last line on the screen. +.scalar ptline ;Cursor is positioned at the end of this line. + +.val.==0 +;;;The line structure describes a single line of the user's display. +def l.next ;The logical next line. +def l.prev ;The logical previous line. +def l.down ;The next line on the user's screen. 0 => last line. +def l.up ;The previous line. 0 => first line. +def l.vpos ;The argument to V to position to the start of this line. +def l.bp.a ;Byte pointer to the beginning of the image of this line. +def l.bp.z ;Byte pointer to the end of the image of this line. +def l.room ;Count of columns of free space to the right of this line. +lline==:.val. ;Length of the line structure. + +.vector window(1+nbits) ;One possible window for each bit, plus one + ;more for the mode line. + +.scalar uname +.scalar xuname +.scalar sname +.scalar hsname + +go: setzi 0, ;Clear flags. + move tt,[-lintpdl,,intpdl-1] ;Set up interrupt pdl. + movem tt,intsp + movei tt,ffpage ;Free all memory. + movem tt,free + .suset [.roption,,a] + tlo a,%opint+%opopc+%oplok+%oplkf + move tt,[-9,,[ .ruind,,u + .soption,,a + .s40addr,,[twenty,,forty] + .smask,,[%pipdl+%piaty] + .smsk2,,[1_usr] + .runame,,uname + .rxuname,,xuname + .rsname,,sname + .rhsname,,hsname + ]] + .suset tt + ;;Initialize the TTY: + .open ttyo,[.uao+%tjdis+%tjmor+%tjctn,,'tty ? setz ? setz] + .lose %lsfil + .open ttyi,[.uai+%tiful+%tinwt+%tiint,,'tty ? setz ? setz] + .lose %lsfil + move tt,[-6,,[ sixbit /ttyopt/ ? movem a + sixbit /height/ ? movem height + sixbit /width/ ? movem width + ]] + syscall ttyvar,[movei ttyi ? tt] + .lose %lssys + aos width ;Because we set %TJCTN. + trne a,%tpmta ;User has a meta bit? + tro %fmeta + tlne a,%tofci ;User has full keyboard? + tro %ffull+%fmeta + tlne a,%tomvu ;User has a display? + tlnn a,%toers + jrst [princ "AError: Terminal must be a display!" + quit] + movsi tt,%tscle+%tsmor+%tssai+%tsfco + tlne a,%tosai ;User has SAIL characters? + troa %fsail ;Yes. + tlz tt,%tssai+%tsfco ;No. + syscall ttyset,[movei ttyi + [<%tgint+%tgact>*<010101,,010101>] + [<%tgint+%tgact>*<010101,,010101>] + tt] + .lose %lssys + +lcmdbuf==:200. ;Length in bytes. +.vector cmdbuf(com"buffer+</5>) + + ;;Initialize CMDBUF: + movei tt,lcmdbuf + movem tt,cmdbuf+com"bsize + movem tt,cmdbuf+com"iwrap + movem tt,cmdbuf+com"owrap + subi tt,1 + movem tt,cmdbuf+com"icount + setzm tt,cmdbuf+com"ocount + movei tt,%bcmd + movem tt,cmdbuf+com"wkmask + movei tt,com"uhang(u) + movem tt,cmdbuf+com"wkaddr + setzm cmdbuf+com"inext + move tt,[440700,,cmdbuf+com"buffer] + movem tt,cmdbuf+com"iptr + movem tt,cmdbuf+com"optr + movei tt,cmdbuf + movem tt,input + + ;;Initialize the screen image: + move e,width + addi e,4 + idivi e,5 + addi e,lline ;E: number of words to allocate per line. + move a,e + imul a,height + addi a,1777 + lsh a,-12 ;A: number of pages needed. + jsp t,alloc + syscall corblk,[movei %cbndr+%cbndw ? movei %jself ? tt ? movei %jsnew] + .lose %lssys + movem a,aline ;A: current line + setzi b, ;B: up line + movei c,8 ;C: vpos arg to V. + movsi d,440700 ;D: byte pointer. + move t,height ;T: loop counter. + move tt,width ;TT: width. +ilinlp: movem b,l.up(a) + movem c,l.vpos(a) + hrri d,lline(a) + movem d,l.bp.a(a) + movem d,l.bp.z(a) + movem tt,l.room(a) + sojle t,ilinex + move b,a + add a,e + movem a,l.down(b) + aoja c,ilinlp + +ilinex: movem a,zline + setzm l.down(a) + move e,height + subi e,1 ;1 line for mode line. + idivi e,2 ;Separating 2 windows. + move a,aline + movem a,window+1 + movei tt,[asciz "> "] + jsp t,prinz + jrst inp1go + +inp1lp: move b,l.down(a) + movem b,l.next(a) + movem a,l.prev(b) + move a,b +inp1go: sojg e,inp1lp + move b,aline + movem a,l.prev(b) + movem b,l.next(a) + move a,l.down(a) + movem a,window+0 + movem a,l.prev(a) + movem a,l.next(a) + movei tt,[asciz "------- Command: "] + jsp t,prinz + movem a,ptline + move a,l.down(a) + movem a,window+2 + movei tt,[asciz "> "] + jsp t,prinz + jrst inp2go + +inp2lp: movem a,l.prev(b) + movem b,l.next(a) + move a,b +inp2go: move b,l.down(a) + jumpn b,inp2lp + move b,window+2 + movem a,l.prev(b) + movem b,l.next(a) + + ;;Contact the demon: +contac: syscall open,[moves e ? [.uii+10,,usr] + [sixbit /usr/] + move duname + move djname] + jrst [ cain e,%ensfl + jrst launch + lose %lsfil(e),.-1 + ] + move t,[-com"npages,,com"page] + move tt,[-com"npages,,com"dpage] + syscall corblk,[movei %cbndr+%cbndw + movei %jself ? move t + movei usr ? tt] + .lose %lssys + ;;AOS the area use counter. + pioff + aos com"count +cntsw1: movei tt,cntswt + movem tt,forty+3 +cntsw2: pion + ;;Initialize process table: + movei tt,p.err + movem tt,proc + move tt,[proc,,proc+1] + blt tt,proc+nbits-1 + movei tt,p.cmd + movem tt,proc+.lz %bcmd + movei tt,p.rip + movem tt,proc+.lz %brip + movei tt,p.aty + movem tt,proc+.lz %baty + ;;Probably safe to handle TTY interrupts now... + .suset [.simsk2,,[1_ttyi]] + hrrzi pi,%baty ;Simulate ATY interrupt first thing. + +wait: jffo pi,wait2 +wait1: skipn com"uhang(u) + .hang + exch pi,com"uhang(u) ;PI must contain 0 here. + jffo pi,wait2 + .lose + +wait2: andcm pi,unjffo(i) + jrst @proc(i) + +.vector proc(36.) + +unjffo: repeat 36., 1_<35.-.rpcnt> + +p.err: princ "AError: Bad process bit set." + lose 0,wait + +p.rip: princ "AError: Demon went away." + lose 0,wait + +p.cmd: movei x,cmdbuf + tyo ["_] + jrst wait + +p.aty: tyo [^P] + tyo ["C] + move a,aline +patylp: move tt,width + sub tt,l.room(a) + jumpe tt,patynx + tyo [^P] + tyo ["V] + tyo l.vpos(a) + move t,l.bp.a(a) + .call sout + .lose %lssys + tyo [^P] + tyo ["H] + tyo [10] +patynx: move a,l.down(a) + jumpn a,patylp + move a,ptline + tyo [^P] + tyo ["V] + tyo l.vpos(a) + tyo [^P] + tyo ["H] + move tt,width + sub tt,l.room(a) + addi tt,8 + tyo tt + jrst wait + +duname: sixbit /.chat./ +djname: sixbit /demon/ + +ddir: sixbit /bawden/ +dfn1: sixbit /chat/ +dfn2: sixbit /demon/ + +launch: .gensym a, + syscall open,[moves e ? [.uio,,usr] + [sixbit /usr/] + movei 0 + move a] + jrst [ cain e,%ensmd + jrst launch + lose %lssys(e),.-1 + ] + syscall open,[[.uii,,dsk] + [sixbit /dsk/] + move dfn1 + move dfn2 + move ddir] + .lose %lsfil + syscall load,[movei usr ? movei dsk] + .lose %lssys + .iot dsk,a + .close dsk, + hrrz a,a + move tt,[-5,,[ .supc,,a + .sxuname,,duname ;XUNAME & XJNAME tell demon + .sxjname,,djname ; what it should call itself. + .shsname,,ddir ;HSNAME is where demon was + ; loaded from. + .ssname,,uname ;SNAME is name of launcher. + ]] + .uset usr,tt + syscall disown,[movsi 5 ? movei usr] + .lose %lssys + movei a,30. ;Wait one second... + .sleep a, + jrst contac + +;;;JSP T,GETMSG to lock a msg bit. Skips if it gets one. Msg bit number +;;;returned in A. +getmsg: movei a,com"lock + movei tt,bitswt + pioff + aose (a) + aoja a,[ + caige a,com"lock+com"nmsgs + jrst .-1 + pion + jrst (t)] +bitsw1: movem a,bitswt + movem tt,forty+3 +bitsw2: pion + subi a,com"lock + movem u,com"user(a) + jrst 1(t) + +;;;JSP T,RELMSG to unlock a msg bit. +relmsg: movei tt,bitswx + pioff + movem tt,forty+3 +bitsw3: setom @bitswt +bitsw4: pion + jrst (t) + +;;;JSP T,SNDMSG to send off a message to the demon. +sndmsg: movei tt,bitswx + pioff + movem tt,forty+3 +bitsw5: move tt,bitswt + subi tt,com"lock + move tt,unjffo(tt) + iorm tt,com"dhang +bitsw6: pion + jrst (t) + +.scalar free ;Number of first free page in memory. + +;;;JSP T,ALLOC to allocate pages. +;;;A: (arg) number of pages desired. +;;;A: (val) address of first allocated word. +;;;TT: (val) -,, +;;; (Suitable for CORBLK) +alloc: hrr tt,a + hrl tt,a + addb a,free + caile a,400 + .lose + subb a,tt + hrrz a,a + lsh a,12 + jrst (t) + +;;;JSP T,PRINZ to print an ASCIZ string in TT into the line in A. +;;;A kludge for the moment. +prinz: hrli tt,440700 + ildb x,tt + jumpe x,(t) +prinzl: idpb x,l.bp.z(a) + sosge l.room(a) + lose 0,. + ildb x,tt + jumpn x,prinzl + jrst (t) + +kill=:jrst . +$kill: pioff + movei tt,com"%kdie + movem tt,com"dhang + .logout 1, + +tsint: intacs,,intsp + %piaty ? 0 ? %piaty ? 0 ? atyint + 0 ? 1_usr ? 0 ? 1_usr ? usrint + 0 ? 1_ttyi ? 0 ? 1_ttyi ? ttyint +ltsint==:.-tsint + +lintpdl==:50. ;Maximum depth: 3 interrupts. +.vector intpdl(lintpdl) +.scalar intsp + +pion=:.suset . +$pion: .spiclr,,[-1] + +pioff=:.suset . +$pioff: .spiclr,,[0] + +dismis: setz + sixbit /dismis/ + movsi intacs + setz intsp + +atyint: tro %faty +disint: .call dismis + .lose %lssys + +usrint: movei tt,%brip + iorm tt,com"uhang(u) + .call dismis + .lose %lssys + +.scalar input + +ttyint: tyi t + jumpl t,disint + trze %faty + jrst [ movei tt,%baty + iorm tt,com"uhang(u) + jrst .+1] + cail t,40 ;Ordinary printing characters are the most + cail t,177 ; common case. + jrst ttycvt +ttyin: skipn x,input + .lose ;Our input is being thrown away! +ttyilp: idpb t,com"iptr(x) + sosge com"iwrap(x) + jrst [ movei tt,com"buffer(x) + hrli tt,440700 + movem tt,com"iptr(x) + move tt,com"bsize(x) + movem tt,com"iwrap(x) + jrst .+1] + sosge com"icount(x) + jrst broken + aos com"ocount(x) + move tt,com"wkmask(x) + iorm tt,@com"wkaddr(x) + skipe x,com"inext(x) + jrst ttyilp + jrst ttyint + +;;;Clip a broken buffer out of our input queue: +broken: movei tt,input ;TT: location of previous pointer. +brokn1: camn x,(tt) ;Is this where it came from? + jrst brokn2 ; Yes. + skipn tt,(tt) ;No. Get next. + lose 0,broken ;Oops! Didn't find it! + movei tt,com"inext(tt) ;Location of its INEXT cell. + jrst brokn1 + +brokn2: move x,com"inext(x) ;Next buffer in queue after broken one. + movem x,(tt) ;Store it in previous buffer. + jumpe x,ttyint + jrst ttyilp + +%TXSUP==:%TXSFT +;;;Odd characters of potential interest: +;;;Top-1 Square +;;;Top-2 Circle +;;;Top-3 Triangle +;;;Top-B Break/Suspend +;;;Top-H Help +;;;Control- End +ttycvt: trne t,%txtop ;Top? + jrst ttytop + ldb tt,[.bp %txasc,t] + cain tt,177 + jrst cvtrub + cain tt,33 + jrst ttytop + caile tt,40 + tro %txctl+100 + + +ttytop: andi t,%txsup+%txmta+%txctl+%txasc + + jrst ttyin + + + + +critic: cntsw1,,cntsw2 + sos com"count + bitsw1,,bitsw2 + setom @a + bitsw3,,bitsw4 + setom @bitswt + bitsw5,,bitsw6 + setom @bitswt +lcritic==:.-critic + +cntswt: com"count + sos @0 ;Always last. + +sout: setz + sixbit /siot/ + movei ttyo + move t + setz tt + +cnstnts: +constants + +variables + +twenty: block 20 + +forty: 0 + 0 + -ltsint,,tsint + 0 + -lcritic,,critic + +pat: block 100. +patch==:pat + +bitswx==:cntswt ;Always 2nd to last. +bitswt: 0 + setom @bitswx + +com"page==:<.+1777>_-12 ;Communications area. + +end go + \ No newline at end of file diff --git a/src/alan/chat.format b/src/alan/chat.format new file mode 120000 index 00000000..dac121f1 --- /dev/null +++ b/src/alan/chat.format @@ -0,0 +1 @@ +alan/chatfm.> \ No newline at end of file diff --git a/src/alan/chatdm.34 b/src/alan/chatdm.34 new file mode 100644 index 00000000..a47e010d --- /dev/null +++ b/src/alan/chatdm.34 @@ -0,0 +1,150 @@ +;;;-*-Midas-*- + +title Chat -- Demon. + +.insrt chat format +com"page==:com"dpage + +a=:1 +b=:2 +c=:3 +d=:4 +e=:5 +t=:6 +tt=:7 ? intacs==:t_6+2 ;T & TT saved by interrupts. + +pi=:15 ;PI=I-1 So JFFO will load I +i=:16 ;Bit numbers kept here. +u=:17 ;UINDs kept here. + +dsk==:1 +usr==:2 + +define syscall name,args + .call [setz ? sixbit /name/ ? args(400000)] +termin + +define lose code,pc + jrst [ syscall lose,[movei code ? movei pc] + .lose %lssys] +termin + +.scalar duname +.scalar djname +.scalar ddir + +go: move tt,[-lintpdl,,intpdl-1] + movem tt,intsp + .suset [.roption,,a] + tlo a,%opint+%opopc + move tt,[-6,,[ .soption,,a + .s40addr,,[twenty,,forty] + .smask,,[%pirlt+%pipdl] + .smsk2,,[0] + .rxuname,,duname + .rxjname,,djname + .rhsname,,ddir + ]] + .suset tt + ;;Create area: + move tt,[-com"npages,,com"page] + syscall corblk,[movei %cbndr+%cbndw+%cbpub + movei %jself ? move tt + movei %jsnew] + .lose %lssys + ;;Initialize area: + setzm com"count + setzm com"tick + setzm com"dhang + setom com"lock + move tt,[com"lock,,com"lock+1] + blt tt,com"lock+com"nmsgs-1 + ;;Install ourselves: + move tt,[-4,,[ sixbit /uname/ ? move duname + sixbit /jname/ ? move djname + ]] + syscall usrvar,[moves e ? movei %jself ? tt] + jrst [ cain e,%etop ;Allow debugging. + jrst .+1 + cain e,%eexfl ;Someone else is it. + .logout 1, + lose %lssys(e),.-1 + ] + + ;;Wake up every minute: + move tt,[%rlset,,[60.*60. ? 0 ? 0 ? 0]] + .realt tt, + ;;Initialize process table: + movei tt,p.msg + movem tt,proc + move tt,[proc,,proc+1] + blt tt,proc+com"nmsgs-1 + movei tt,p.die + movem tt,proc+.lz com"%kdie + movei tt,p.rlt + movem tt,proc+.lz com"%krlt + setzi pi, + jrst wait1 + +wait: jffo pi,wait2 +wait1: skipn com"dhang + .hang + exch pi,com"dhang ;PI must contain 0 here. + jffo pi,wait2 + .lose + +wait2: andcm pi,unjffo(i) + jrst @proc(i) + +.vector proc(36.) + +unjffo: repeat 36., 1_<35.-.rpcnt> + +p.msg: move tt,com"msg(i) + movem tt,lstmsg' + move tt,com"user(i) + movem tt,lstuser' + setom com"lock(i) + jrst wait + +p.die: .logout 1, + +p.rlt: aos com"tick + jrst wait + +tsint: intacs,,intsp + %pirlt ? 0 ? %pirlt ? 0 ? rltint +ltsint==:.-tsint + +lintpdl==:50. ;Maximum depth: one interrupt. +.vector intpdl(lintpdl) +.scalar intsp + +dismis: setz + sixbit /dismis/ + movsi intacs + setz intsp + +rltint: movei tt,com"%krlt + iorm tt,com"dhang + .call dismis + .lose %lssys + +cnstnts: +constants + +variables + +twenty: block 20 + +forty: 0 + 0 + -ltsint,,tsint + +pat: block 100. +patch==:pat + +ifg .-, .err DPAGE too low. + +end go + \ No newline at end of file diff --git a/src/alan/chatfm.12 b/src/alan/chatfm.12 new file mode 100644 index 00000000..8510265c --- /dev/null +++ b/src/alan/chatfm.12 @@ -0,0 +1,71 @@ +;;;-*-Midas-*- + +;;; Chat communications area format. + +.begin com + +define defloc name,size=1 +name=:.loc. +.loc.==.loc.+ +termin + +define def name,size=1 +name==:.val. +.val.==.val.+ +termin + +dpage==:10 ;Starting on page 10 in the demon. +maxj==:150. ;MC currently has 120. jobs. + +;;;Pre-allocated bits in DHANG +%k==:525252,,525252 +%krlt==:1_0 ;Realtime interrupt. +%kdie==:1_1 ;Request to terminate. +nmsgs==:34. ;The rest are msg bits. + +;;;Buffer format. All sizes are in bytes. Entries marked with a star are +;;;initialized by the demon from information supplied in the initial messages. +.val.==0 +def iuser ;* UIND of input side. +def ouser ;* UIND of output side. +def bsize ;* Total space in buffer. +def icount ;* Count of free space minus one. If the input side + ;deposits a byte and decrements this count to be -1, then + ;it must consider the connection to be broken. If the + ;output side increments this count and it becomes 0, then + ;it knows that the connection has been broken. +def ocount ;* Count of occupied space. Incremented by the output side + ;AFTER depositing a byte but BEFORE delivering the wakeup. + ;If the input side decrements this to 0, then it knows it + ;will recieve a wakeup when the next byte in input. +def wkmask ;* A mask of bits to use to wake up the output side. +def wkaddr ;A pointer to the output side's UHANG word. For use by the + ;input side. +def inext ;The input side uses this to build a linked list of + ;buffers. +def iwrap ;Count of empty space before wraparound for input side. +def owrap ;Count of empty space before wraparound for output side. +def iptr ;Byte pointer for input side. +def optr ;Byte pointer for output side. +def buffer ;First location of buffer. + +ifdef page,[ + +.loc.==page_12 + +defloc count ;Count of jobs using the area. +defloc tick ;Demon increments this every minute. +defloc uhang,maxj ;Users hang on bits in these words. +dhang==:uhang+0 ;Demon hangs on bits in this word. + ; (SYS job can't be a user!) +defloc lock,nmsgs ;Locks for msg bits in DHANG. +defloc user,nmsgs ;UIND of owners of locks. +defloc msg,nmsgs ;Messages. + + +npages==:<<.loc.+1777>_-12>-page + +] ;end ifndef page, + +.end com + \ No newline at end of file