.TITLE LIBMAC .IDENT /V01.05/ .ENABL LC .NLIST BEX ; Don't list binary extensions .SBTTL Macro Calls and Definitions .MCALL DIR$ ; Execute directive .MCALL QIOSY$ ; Define QIO symbols .MCALL QIOW$ ; Queue I/O and wait .MCALL ASTX$S ; Exit from AST state .MCALL CLEF$S ; Clear event flag .MCALL EXIT$S ; Exit to RSX .MCALL GTSK$ ; Get task information .MCALL STSE$S ; Stop for single event flag .MCALL SETF$S ; Set event flag .MCALL STOP$S ; Stop .MCALL TTSYM$ ; Define terminal driver symbols QIOSY$ TTSYM$ .PAGE .SBTTL .SBTTL Data .SBTTL .PSECT MACIMP, RW, D ASTPC == 4 ; offset on AST stack to PC ESC = 33 ; Escape .SBTTL Directive Parameter Blocks GETTSK: GTSK$ TSKBUF ATT: QIOW$ IO.ATA!TF.NOT,7,,,,, ; Specify KB AST;01.09 DET: QIOW$ IO.DET,7,1 ; Dump the terminal FIND: QIOW$ SF.GMC,7,1,,,, TRMIO: QIOW$ IO.WAL,7,1,,,,<0, 0> TTYGET: QIOW$ SF.GMC,7,1,,,, ; Get buff len ;01.09 TTYKIN: QIOW$ IO.RNE!TF.RAL,7,1,,,, ; Get KBD input ;01.09 TTYFLU: QIOW$ SF.SMC,7,1,,,, ; Flush KB buff ;01.09 TTYOUT::QIOW$ IO.WVB,7,1,,,,<0, 0, 40> ; Write, std carr cntrl .PAGE .SBTTL Tables .PAGE .SBTTL Strings and Text S1: .ASCII \[\ S1A: .ASCII \00\ .ASCII \;\ S1B: .ASCII \00\ .ASCII \H\ S1L = . - S1 S2: .ASCII /[1;1H/ ; Home the cursor S2L = . - S2 S3: .ASCII /[0J/ ; Erase to end of screen S3L = . - S3 S4: .ASCII /[0K/ ; Erase to end of line S4L = . - S4 S5: .ASCII /[?2l/ ; Spectacular startup screen S5L = . - S5 S6: .ASCII \Sorry, mate, your terminal is not a VT100. Exiting. Gudday.\ S6L = . - S6 S7: .ASCII \Sorry, mate, your terminal is not set /NOWRAP. Exiting. Gudday.\ S7L = . - S7 S8: .ASCII \Stopping for control-C. To proceed, type "UNS \ S8A: .BLKB 6 .ASCII \".\ S8L = . - S8 S10: .ASCII \[1;5m\ S10L = . - S10 S11: .ASCII \[0m\ S11L = . - S11 .EVEN .PAGE .SBTTL Variables BUFF: .BYTE TC.TTP, 0 .BYTE TC.ACR, 0 BUFFL = . - BUFF GETTBL: .BYTE TC.TBF,0 ; GMC/SMC buffer;01.09 KBSTPT: .WORD 0 KBGTPT: .WORD 0 KBBUF: .BLKB 32. RETADD: .WORD 0 TSKBUF: .BLKW 16. WRKBUF: .BLKB 256. .EVEN .PAGE .SBTTL DOLINE .PSECT DOLINE, RO, I ; Put out a sequence of characters processed for special attributes ; on the VT100 screen. Note that the input array is INTEGER so every ; other byte has to be skipped. ; ; Calling sequence: CALL DOLINE (1st byte, # bytes) DOLINE::MOV 2(R5), R0 ; Load 1st output char address MOV @4(R5), R1 ; Load #original characters to print MOV #WRKBUF, R2 ; Load work buffer address in R2 10$: MOV R0, TRMIO+Q.IOPL ; Load current output char address CMPB (R0), #'X ; Is it an enemy city? BEQ 30$ ; If so, go do it CMPB (R0), #'A ; Is it one of the player's pieces? BLO 40$ ; If not, go see if it's an enemy piece CMPB (R0), #'Z ; Is it one of the player's pieces? BHI 40$ ; If not, go see if it's an enemy piece ; The player owns this piece; go bright, print it, clear bright MOVB #ESC, (R2)+ ; Load bright sequence: ESC[1m MOVB #'[, (R2)+ MOVB #'1, (R2)+ MOVB #'m, (R2)+ MOVB (R0)+, (R2)+ ; Copy input byte MOVB #ESC, (R2)+ ; Clear bright sequence: ESC[0m MOVB #'[, (R2)+ MOVB #'0, (R2)+ MOVB #'m, (R2)+ BR 70$ ; See if the enemy owns this piece 40$: CMPB (R0), #'a ; Is it one of the machine's pieces? BLO 50$ ; If not, just go print it CMPB (R0), #'z ; Is it one of the machine's pieces? BHI 50$ ; If not, just go print it ; The computer owns this piece; blink it, print it, clear blink 30$: MOVB #ESC, (R2)+ ; Load bright blink sequence: ESC[1;5m MOVB #'[, (R2)+ MOVB #'1, (R2)+ MOVB #';, (R2)+ MOVB #'5, (R2)+ MOVB #'m, (R2)+ MOVB (R0)+, (R2)+ ; Copy input byte MOVB #ESC, (R2)+ ; Clear bright sequence: ESC[0m MOVB #'[, (R2)+ MOVB #'0, (R2)+ MOVB #'m, (R2)+ BR 70$ ; Just an ordinary piece; print it 50$: MOVB (R0)+, (R2)+ 70$: INC R0 ; Point past unused upper byte SOB R1, 10$ ; And loop until all done ; Figure out how long the line is and print it on the terminal SUB #WRKBUF, R2 ; R2 now contains the line length MOV #WRKBUF, TRMIO+Q.IOPL ; Load work buffer address into QIO DPB MOV R2, TRMIO+Q.IOPL+2 ; And the length also DIR$ #TRMIO ; Print the reworked buffer RETURN ; Return to the caller .PAGE .SBTTL LIBCUR .PSECT LIBCUR, RO, I ; Move the cursor to the position specified by the calling parameters. ; ; Calling sequence: CALL LIBCUR (LINE, COLUMN) LIBCUR::TST (R5)+ ; Skip over first word at call site MOV #S1A, R0 ; Load output field address MOV @(R5)+, R1 ; Load line number MOV #011012, R2 ; Radix 10, 2 wide, no 0 suppress CALL $CBTA ; Convert binary to ASCII MOV #S1B, R0 ; Load output field address MOV @(R5)+, R1 ; Load column number MOV #011012, R2 ; Radix 10, 2 wide, no 0 supprss CALL $CBTA ; Convert binary to ASCII MOV #S1, TRMIO+Q.IOPL MOV #S1L, TRMIO+Q.IOPL+2 DIR$ #TRMIO ; Do the terminal output RETURN ; Return to the caller .PAGE .SBTTL LIBPGE .PSECT LIBPGE, RO, I LIBPGE::TST (R5) BEQ 1$ CALL LIBCUR MOV #S3, TRMIO+Q.IOPL MOV #S3L, TRMIO+Q.IOPL+2 DIR$ #TRMIO RETURN ; Return to the caller 1$: MOV #S2, TRMIO+Q.IOPL MOV #S2L, TRMIO+Q.IOPL+2 DIR$ #TRMIO RETURN ; Return to the caller .PAGE .SBTTL LIBLIN .PSECT LIBLIN, RO, I LIBLIN::TST (R5) BEQ 1$ CALL LIBCUR 1$: MOV #S4, TRMIO+Q.IOPL MOV #S4L, TRMIO+Q.IOPL+2 DIR$ #TRMIO RETURN ; Return to the caller .PAGE .SBTTL STTRM .PSECT STTRM, RO, I STTRM:: CALL STTRM1 CALL MAPSET RETURN ; Return to the caller STTRM1: DIR$ #ATT DIR$ #FIND ; Get multiple characteristics for TI: CMPB BUFF+1, #T.V100 ; Is the host terminal set to VT100? BEQ 3$ ; If so, proceed ; The host is not a VT100; show error message and die MOV #S6, TTYOUT+Q.IOPL ; Load error message address MOV #S6L, TTYOUT+Q.IOPL+2 ; Load error message length DIR$ #TTYOUT ; Print the error message EXIT$S ; Exit to RSX ; OK, groovy, it's a VT100. See if /NOWRAP is set. 3$: TSTB BUFF+3 ; Is /WRAP set? BEQ 4$ ; If not, proceed ; The host is not set /NOWRAP; show error message and die MOV #S7, TTYOUT+Q.IOPL ; Load error message address MOV #S7L, TTYOUT+Q.IOPL+2 ; Load error message length DIR$ #TTYOUT ; Print the error message EXIT$S ; Exit to RSX ; The host is a VT100 set /NOWRAP; return to the caller 4$: RETURN ; Return to the caller .PAGE .SBTTL TERMIO .PSECT TERMIO, RO, I GETC:: CLRB GETTBL+1 DIR$ #TTYFLU GETC1: CMP KBSTPT, KBGTPT BNE 1$ CALL KBWAIT BR GETC1 1$: MOV @KBGTPT, R0 INC KBGTPT RETURN ; Return to the caller ; ;01.09 ; Check for async input. ;01.09 ; ;01.09 KBDCHK:: ; Look for async CTRL/E.;01.09 MOV R0,-(SP) ; Save R0 ;01.09 MOV R4,-(SP) ; Save R4 ;01.09 MOV #KBBUF,R4 ; Point to buffer start ;01.09 MOV KBGTPT,R0 ; And to where we are ;01.09 MOV R4,KBGTPT ; Bottom is now at start;01.09 10$: CMP R0,KBSTPT ; At end yet? ;01.09 BEQ 20$ ; Yes, finish up. ;01.09 MOVB (R0)+,(R4)+ ; Copy the next byte ;01.09 BR 10$ ; Keep it going ;01.09 20$: MOV R4,KBSTPT ; New top-of-buffer ;01.09 DIR$ #TTYGET ; Get char count from KB;01.09 MOVB GETTBL+1,R0 ; Copy count into R0 ;01.09 BEQ 30$ ; No more input, exit. ;01.09 MOV R4,TTYKIN+Q.IOPL ; Point at free area ;01.10 MOV R0,TTYKIN+Q.IOPL+2 ; And how many to get ;01.09 ADD R4,R0 ; Add start to count ;01.09 CMP R0,#KBBUF+74. ; Will it all fit? ;01.09 BHI 30$ ; No, then don't do it. ;01.09 DIR$ #TTYKIN ; Get the input chars ;01.09 MOV R0,KBSTPT ; Store new end-of-buff ;01.09 30$: MOV (SP)+,R4 ; Restore (CHAR), ;01.09 MOV (SP)+,R0 ; Also TEMP ;01.09 RETURN ; And exit. ;01.09 ; ;01.09 ; Keyboard Input "wait" routine. Gets input if any,else waits for KNOTFY;01.09 ; to set Event Flag 10 and looks again for input. ;01.09 ; ;01.09 KBWAIT::CLEF$S #10. ; Clear the event flag ;01.09 CALL KBDCHK ; Do input if possible ;01.09 MOVB GETTBL+1,R0 ; See if we did any ;01.09 BNE 30$ ; Yes, exit now. ;01.09 STSE$S #10. ; Wait for a signal ;01.09 BR KBWAIT ; See if it was right ;01.09 30$: RETURN ; Success, return. ;01.09 ; ;01.09 ; Unsolicited-input notification AST. ;01.09 ; ;01.09 KNOTFY: SETF$S #10. ; Don't need to do much ;01.09 TST (SP)+ ; Clean up the stack, ;01.09 ASTX$S ; Exit the AST service ;01.09 ; ;01.09 ; Control-C AST handler ;01.09 ; ;01.09 KNTRLC::TST (SP)+ ; Pop a word off stack ;01.09 MOV 2(SP), RETADD ; Save the old return. MOV #ERROR0,2(SP) ; Point at the Control-C code SETF$S #10. ; Set input event flag ;01.09 ASTX$S ; Exit from KB AST ;01.09 ERROR0: DIR$ #DET ; Let go of our host terminal MOV #S2, TRMIO+Q.IOPL MOV #S2L, TRMIO+Q.IOPL+2 DIR$ #TRMIO ; Home the cursor MOV #S3, TRMIO+Q.IOPL MOV #S3L, TRMIO+Q.IOPL+2 DIR$ #TRMIO ; Clear the screen MOV #S4, TRMIO+Q.IOPL MOV #S4L, TRMIO+Q.IOPL+2 DIR$ #TRMIO ; Clear the screen DIR$ #GETTSK ; Get task information MOV #S8A, R0 ; Load taskname buffer address MOV TSKBUF+G.TSTN, R1 ; Load taskname 1st half CALL $C5TA ; Convert R50 to ASCII MOV TSKBUF+G.TSTN+2, R1 ; Load taskname 2nd half CALL $C5TA ; Convert R50 to ASCII MOV #S8, TRMIO+Q.IOPL MOV #S8L, TRMIO+Q.IOPL+2 DIR$ #TRMIO ; Print message STOP$S ; Stop the task for later. CALL STTRM1 ; Reset the terminal MOV RETADD, -(SP) ; Get the re-start address. RETURN ; Return to the caller .END