.MCALL .MODULE .MODULE ZRT,RELEASE=X00,VERSION=21,COMMENT=,AUDIT=NO ;+ ; ; Copyright (c) 2000 by Megan Gentry ; Framingham, Massachussetts ; All Rights Reserved ; Commercial Use and Distribution Prohibited ; ; This software was developed for use with the Z-machine emulator by ; Johnny Billquist. In this context, rights are hereby granted by ; the author for the software to be freely copied and used in its ; entirety for any non-commercial purpose so long as the above ; copyright notice and these comments are preserved. ; ; The author has used best efforts in the research, design, development ; and testing of this software. The author makes no warranty of any ; kind, expressed or implied, with regard to this software and its ; suitability for a given application. The author shall not be liable ; in any event for incidental or consequential damages in connection ; with, or arising out of, the use or performance of this software. Use ; of this software constitutes acceptance of these terms. ; ; The author is committed to making a best effort at fixing any errors ; found in the software and welcomes any reports of problems, comments, ; or suggestions regarding the software at . ; ;- .SBTTL Abstract and Edit History ;+ ; ; ZRT ; This module implements the support routines used by the ; Z-emulator in a manner specific to the RT-11 operating ; system. It is modelled after the ZRSX module. ; ; Portions Copyright (c) 2000 by Johnny Billquist ; ; Edit History: ; Note that several of the RSX-specific library routines have ; had RT-11 equivalents written. These can be found in module ; ZRTLIB.MAC ; ; (00) 10-Aug-2000 Megan Gentry ; Initial RT-11 related coding ; ; (01) 29-Aug-2000 Megan Gentry ; o RT-ified several routines, including ZMSG, PUTTXT, GETRND, ; CHARNE, ZEXIT, ZALLOC. Still some questions about aspects ; of some of the routines. ; ; (02) 30-Aug-2000 Megan Gentry ; o Completed conditionalization of code so it should be ; buildable on RSX... RT still needs some work. ; ; (03) 06-Sep-2000 Megan Gentry ; o Added printout of program name, commented out ; o Adding code to ZINIT to parse file name string and ; process options ; ; (04) 07-Sep-2000 Megan Gentry ; o Added code to determine and report a non-scope (unknown) ; vs. a scope (vt100) terminal. Added option which allows ; specification of a terminal type. ; ; (05) 10-Sep-2000 Megan Gentry ; o Added code to match new routines in ZRSX which handle ; terminal input timeout ; ; (06) 13-Sep-2000 Megan Gentry ; o Added code to match new routines in ZRSX which handle ; game save/restore ; ; (07) 14-Sep-2000 Megan Gentry ; o ZALLOC was returning pointer to top of allocated memory, ; not to the start of the allocated region. ; o In ZBLK, the amount to read is specified in bytes, but ; RT uses words. ; o In INPINI, wasn't correctly checking for 0 timeout. ; o In INPINI, MUL uses two registers, which affected the check ; for the system clock frequency. It also was taking the ; low-order timeout value from the wrong place. Converted to ; using single-precision inline code. ; o In INPINI, option processing code was not correctly using ; the option count (it was referring to the wrong register) ; and instead of branching back for the next option, it ; branched back to prompt again for a command. ; ; (08) 15-Sep-2000 Megan Gentry ; o Recoded timer and character input routines to match what ; is in ZRSX. ; o Added code to allocate space for multiple queue elements ; so disk I/O can occur while a timer is active. ; o Added code to ensure that PAR1 space cannot be allocated ; ; (09) 16-Sep-2000 Megan Gentry ; o Changes due to comments from Johnny Billquist -- SAVE/ ; RESTORE code doesn't need to add s to filename strings, ; they're already there. New method of aborting, calling ; ABORT before calling ZEXIT ; o Reduced code a little by having RESCLO call SAVCLO, since ; they do the exact same thing... ; ; (10) 18-Sep-2000 Megan Gentry ; o Modifications to random number routine -- using generator ; algorithm specified in Knuth, Vol.II (with some values ; which follow the rules, but may not produce a great random ; number sequence). ; o Added seed value for random number generator as a command ; line option (/S:value). ; ; (11) 19-Sep-2000 Megan Gentry ; o Modifications to SAVBLK and RESBLK. Neither was specifying ; the block number (RTSBLK) to be used for the write. ; o My misunderstanding of the purpose of GETRND had me write ; a full random-number generator, when all that was needed ; was a seed value for a generator in the ZEMU common code. ; This has been corrected. ; ; (12) 20-Sep-2000 Megan Gentry ; o Corrected assembly problems when DBUG was enabled ; o Added new debug flags for tracing entry to the RT ; routines and for the timeout routine. ; o Extended debug/trace messages ; ; (13) 21-Sep-2000 Megan Gentry ; o ZMSG routine was using an incorrect offset for getting ; at stacked values due to differences in the $SAVAL ; routines (RT vs. RSX). Problem found by JB. ; o Added code at PUTTXT to ignore zero or negative length ; strings. ; o Recoded GETSLN so that it won't return a zero value ; o Added entries to RTTTTB only to find that the offset into ; the table returned the same value, so the routine GETSTP ; can be much simpler. ; ; (14) 22-Sep-2000 Megan Gentry ; o Recoded GETSCL and GETSTP routines so that they work ; correctly in the virtual environment of vrun/vbgexe by ; using .PEEK to get to the actual structures in low ; memory. ; ; (15) 18-Oct-2000 Megan Gentry ; o Conditionalized default terminal type ; ; (16) 30-Oct-2000 Megan Gentry ; o Johnny's been busy again... had to add support for logging ; (scripting). ; ; (17) 01-Nov-2000 Megan Gentry ; o Finally got to test scripting, had a few bugs to fix. ; ; (18) 02-Nov-2000 Megan Gentry ; o Coding changes to scripting routines so that once a write ; failure has occurred, the script is closed and a flag set ; so that future calls to SCRBLK are ignored until a new ; file has been opened. ; ; (19) 17-Aug-2003 Johnny Billquist ; o Added CHESIZ, CHEALL and CHEUPD for a more general cache ; handling. ; ; (20) 30-Apr-2006 Johnny Billquist ; o Added some more missing stuff for the current version to build. ; ; (21) 04-Sep-2008 Johnny Billquist ; o Changed calling sequence for INPINI ;-- .INCLUDE /ZMAC/ ;Z-Machine definitions D.RTRC =: 100000 ;RT subroutine trace INTVER == 103 ; Interpreter version "C" .SBTTL RT-11 System Macro Declarations ; List the RT-11 programmed requests we'll be using .MCALL .GTLIN .TTYIN .PRINT ;Terminal I/O .MCALL .RCTRL .TTINR .MCALL .CSISP ;Filespec parsing .MCALL .ENTER .LOOKU .CLOSE ;File access .MCALL .READW .WRITW .MCALL .SETTO ;Program size .MCALL .GVAL ;System information .MCALL .PEEK .MCALL .GTIM .DATE ;Date/time information .MCALL .MRKT .CMKT ;Timer control .MCALL .EXIT .QSET ;Job control ; Now declare and invoke the structure definitions .LIBRARY /SY:SYSTEM.MLB/ ; Configuration word 1 .MCALL .CF1DF .CF1DF ; .CSI returned information .MCALL .CSIDF .CSIDF ; .CSTAT information block .MCALL .CSTDF .CSTDF ; RT-11 Internal Date .MCALL .DATDF .DATDF ; File specification DBLK (returned by CSI) .MCALL .DBKDF .DBKDF ; Default file extensions (for CSI) .MCALL .DFXDF .DFXDF ; .SDTTM date/time block .MCALL .DTMDF .TIMDF .DTMDF .TIMDF ; EMT error codes .MCALL .ERRDF .ERRDF ; RT-11 RMON Fixed Offset Area .MCALL .FIXDF .FIXDF ; .GTJB returned information block .MCALL .GTJDF .GTJDF ; Job Status Word .MCALL .JSWDF .JSWDF ; Queue element layout .MCALL .QELDF .QELDF ; RT-11 System Communications Area .MCALL .SYCDF .SYCDF ; Terminal Configuration .MCALL .TCFDF .TTCDF .TCFDF .TTCDF ; Miscellaneous definitions RTTID ==: 1 ;Read timer ID RTQELN ==: 1+1+1+1 ;Number of extra Qelements needed ; timer, game file read, save/restore ; and scripting RTGCHN ==: 10 ;Channel for game file RTSCHN ==: 11 ;Channel for game save/restore RTLCHN ==: 12 ;Channel for scripting (log) file .SBTTL Locally-defined macros ; Define some locally needed structures .MCALL .DSECT .DS .DSECT ;Option table entry .DS SW.OCH,,B ;Option character .DS SW.OFG,,B ;Option flags .DS SW.OAD ;Option value address .DS SW.ODF ;Option default value .DS SW.ESZ,0 .MCALL .BSECT .BS .BSECT .BS SW$FLG ;Option is flag only (0 = value) .BS SW$DEF ;Option has a default value .BS SW$REQ ;Option requires value .BS SW$FIL ;Option is file-oriented ; The following macro is used to specify the options which are ; supported by this program. .MACRO SWDEF CHAR,FLAGS,LABEL,DEFALT $$$ = . .BYTE ''CHAR .BYTE .WORD LABEL .IF NB DEFALT .WORD DEFALT . = <$$$ + SW.OFG> .BYTE !SW$DEF .IFF ;NB DEFALT .WORD 0 . = <$$$ + SW.OFG> .BYTE & <-SW$DEF> .ENDC ;NB DEFALT . = <$$$ + SW.ESZ> .ENDM ;SWDEF .SBTTL Impure data area (RT-11 specific) .PSECT DATA,D,RW RTNAME: .ASCII |ZEMU/RT | ; : Identification string .NLCSI TYPE=I,PART=RLSVER ; : Version .ASCIZ / / RTFNMP: .ASCII /Game filename? /<200> ; : File name prompt .EVEN GAMID:: ; Junk game identification in save file RTIBUF: .BLKB 132. ; : Input buffer RTSPSV: .BLKW ; : SP storage ; Define the options (switches) we recognize ; *** Begin Critical Ordering *** RTSWTB: SWDEF B,,CLIM ; /B:n (number of cache pages) SWDEF D,,DBGFLG ; /D:n (debug flag) SWDEF I,,INTERP ; /I:n (force interpreter level) SWDEF S,,RTOPTS ; /S:n (set random number seed) SWDEF T,,RTOPTT ; /T:n (terminal type) .WORD 0 ; ** Table Fence ** ; *** End Critical Ordering *** RTAREA: .BLKW 10. ; : Area for RT programmed requests RTDTBK: .BLKW ; : Date word RTTMBK: .BLKB TIM.SZ ; : Time block .SBTTL Impure data area - common to all supported OSes .PSECT DATA,D,RW ; Data area for .BLK macro arguments... (used by all flavors of module) ; ** NOTE ** In RT-11, blocks are 16-bit values. BPAGE:: .WORD 0 ; These values are written BADDR:: .WORD 0 ; by ZMAC macros... BCNT:: .WORD 0 ; Therefore they must exist. INFO:: .LIMIT ; : Image limits, link-time FREEPT: .BLKW ; : Highest address in use (run-time) END: .WORD 0 ; : Highest address allocated (run-time) BUF:: .BLKB 256. ; : Space for expanding strings .SBTTL ZMSG - Prints a message at the user's terminal ;+ ; ; ZMSG shall print a message on the users terminal. The string ; will have a CRLF appended. ; The function is used on errors. ; ; In: R1 -> NUL-terminated string. ; 2(SP) - A list of arguments for the string. ; ; No registers should be changed. ; ; The formatting used is that of $EDMSG in RSX. ; ; The string formatting is kindof like printf() in C, in that ; special codes in the string are replaced by the arguments ; pointed at in the argument list. ; ; Special formatting characters are: ; ; %D - signed decimal. ; %O - signed octal. ; %M - unsigned octal with leading zeroes. ; %P - unsigned octal. ; %U - unsigned decimal. ; %B - unsigned octal byte. Argument is address of byte. ; ;- .PSECT CODE,I,RO .ENABL LSB ZMSG:: ;;;; ** NOTE ** Cannot do this without causing an endless loop ;;; .DBG #D.RTRC,<"[Entered ZMSG]"> CALL $SAVAL ; Save registers. MOV #BUF,R0 ; Buffer in R0. MOV SP,R2 ; Argument block. ADD #22,R2 ; account for saved registers CALL $EDMSG ; Format message. .PRINT #BUF ;Print the string with RETURN ; Done. .DSABL LSB .SBTTL PUTTXT - Writes text to the screen ;+ ; ; PUTTXT is the routine to write a text to the screen. ; ; In: R0 - Address of text. ; R1 - Length of text. ; ; Note that the text is NUL terminated. ; The NUL is not accounted for in the length, though. ; ;- .PSECT CODE,I,RO .ENABL LSB PUTTXT:: .DBG #D.RTRC,<"[PUTTXT: Address = %P, count = %D. characters]">,R0,R1 TST R1 ;Anything to print? BEQ 10$ ;Nope... BMI 10$ ;Negative strings lengths are absurd MOV R0,-(SP) ;Copy the string start pointer ADD R1,R0 ;Add length, now points to end MOVB #200,@R0 ;Flag to terminate without MOV @SP,R0 ;Restore pointer to string .PRINT ;Print the string MOV (SP)+,R0 ;Restore pointer to string 10$: RETURN .DSABL LSB .SBTTL GETRND - Get a random value ;+ ; ; GETRND ; Returns a 16-bit random value to be used as a seed to the ; random number generator. ; ; Call: ; none ; ; Return: ; R0 = 16-bit random value ; ; Notes: ; o The seed value can be specified by an option (/S:seed) and ; will be used without modification. This is useful when ; attempting to debug the random number generator. ; o If not otherwise specified, this routine will return the ; lo-order 16 bit RT-11 time value, which is a monotonically ; increasing value indicating the number of clock ticks which ; have occurred since midnight. The lo-order value wraps ; every 18 minutes. ; ;- .PSECT CODE,I,RO .ENABL LSB GETRND:: MOV RTOPTS,R0 ;Was a seed specified via option? BNE 10$ ;Yep... use it... .GTIM #RTAREA,#RTTMBK ;Get the RT-11 time MOV RTTMBK+TIM.LO,R0 ; and return the lo-order 16 bits 10$: .DBG #D.RTRC,<"[GETRND: returning %P as seed]">,R0 RETURN .DSABL LSB .PSECT DATA,D,RW RTOPTS: .WORD 0 ; : Random number seed .SBTTL INPINI - Input read timer initialization ;+ ; ; INPINI ; Sets a timer for terminal input ; ; Call: ; TMO = timeout, in 1/10s of a second ; ; Return: ; none, registers preserved ; ; Errors: ; none ; ;- .PSECT CODE,I,RO .ENABL LSB INPINI:: .DBG #D.RTRC,<"[INPINI: timeout = %D. tenths of a second]">,R0 MOV R0,-(SP) ;Save some registers for awhile MOV R1,-(SP) ; ... CLR RTRTEN ;Disable the repeating interval timer .CMKT #RTAREA,#RTTID ;Cancel any outstanding read timer CLR RTRTFG ;Reset the read timer flag .GVAL #RTAREA,#$CNFG1 ;Get configuration word 1 MOV R0,R1 ;Save it for later MOV TMO,R0 ;R0 = Specified timeout BEQ 20$ ;No timeout... ASL R0 ;Convert tenths to ticks (assume 60hz) MOV R0,-(SP) ; using ASL R0 ; inline ADD (SP)+,R0 ; code BIT #CLK50$,R1 ;Does system have a 50-hz clock? BEQ 10$ ;Nope... SUB TMO,R0 ;Yes, adjust ticks for 50-hz clock 10$: CLR RTRTBK ;Set read timer hi-order MOV R0,RTRTBK+2 ; and lo-order timeout value CLR RTRTFG ;Reset the timeout flag MOV SP,RTRTEN ;Enable the repeating interval timer .MRKT #RTAREA,#RTRTBK,#RTRTCR,#RTTID ;Post the timeout BCC 20$ ;success... .MSG <"No queue element available for timer"> 20$: MOV (SP)+,R1 ;Restore previously saved registers MOV (SP)+,R0 ; ... RETURN .DSABL LSB .PSECT DATA,D,RW RTRTFG: .BLKW ; : Read timeout flag RTRTEN: .BLKW ; : Read timer enable RTRTBK: .BLKW 2 ; : Read timeout timer block .SBTTL INPEND - Cancel read timer ;+ ; ; INPEND ; Cancels any outstanding timer for terminal input ; ; Call: ; none ; ; Return: ; none ; ; Errors: ; none, registers preserved ; ; Notes: ; o The only possible error from .CMKT is ignored since the ; result is the same as if there is no error. ; ;- .PSECT CODE,I,RO .ENABL LSB INPEND:: .DBG #D.RTRC,<"[INPEND: timer cancelled]"> MOV R0,-(SP) ;Save some registers for awhile CLR RTRTEN ;Disable the repeating interval timer .CMKT #RTAREA,#RTTID ;Cancel any outstanding read timer CLR RTRTFG ;Reset read timer timeout flag MOV (SP)+,R0 ;Restore previously saved register RETURN .DSABL LSB .SBTTL RTRTCR - Read timer completion routine ;+ ; ; RTRTCR ; This completion routine is entered upon input read timer timeout. ; ; Entered with: ; R0 = Timer ID ; ; Implicit Output: ; timer timeout flag is set ; ; Notes: ; o Registers are preserved (they must be, since this is a ; completion routine. ; ;- .PSECT CODE,I,RO .ENABL LSB RTRTCR: .DBG #D.RTRC,<"[!!Timeout has occurred!!]"> MOV SP,RTRTFG ;Set the timeout flag RETURN .DSABL LSB .SBTTL CHARNE - Read a character from keyboard, no echo ;+ ; ; CHARNE ; Read one character from keyboard, with no echo. ; ; Returns: ; R0 = Character ; ; Notes: ; o In RT-11, the key is converted into the sequence ; . This happens even when the terminal is in ; special mode. ; ; o In order to return only one character, this routine will ; discard any which immediately follows a . It ; will, however, pass a for which the previous character ; was NOT a . ; ;- .PSECT CODE,I,RO .ENABL LSB CHARNE:: BR 20$ ;Try at least once for character... 10$: TST RTRTFG ;Did the read timer time-out? BEQ 20$ ;Nope... CLR RTRTFG ;Yes, consume the timeout TST RTRTEN ;Is the timer still enabled? BEQ 20$ ;No... .MRKT #RTAREA,#RTRTBK,#RTRTCR,#RTTID ;Post a new timer BCC 15$ ;Success... .MSG <"No queue element available for timer"> 15$: CLR R0 ;Return a .DBG #D.RTRC,<"[CHARNE: Returning timeout]"> SEC ; with carry set BR 40$ 20$: .TTINR ;Try for a character BCS 10$ ;None available yet... CMPB R0,#<^o12> ;Is it a ? BNE 30$ ;Nope... CMPB RTLCHR,#<^o15> ;Yes, Was previous character a ? BNE 30$ ;Nope, so pass this MOVB R0,RTLCHR ;Yes, so save this as last character BR 10$ ; and go try again 30$: MOVB R0,RTLCHR ;Save this as new last character .DBG #D.RTRC,<"[CHARNE: returning character %O]">,R0 CLC ; which we return with carry clear 40$: RETURN .DSABL LSB .PSECT DATA,D,RW RTLCHR: .BYTE 0 ; : Last character received .EVEN .SBTTL ZINIT - Initialization routine ;+ ; ; ZINIT ; This is the game initialization routine. It queries the ; user for the name of a game file (repeating until valid) ; and processes any options. ; ; Notes: ; o RT-11 provides a single queue element, typically used ; for I/O. Since the timer consumes a queue element, this ; would prevent doing any I/O while a read timer is active. ; We need to allocate space for a couple of queue elements ; and let RT know about them (.QSET) ; ; o Ensure that no part of allocated space can exist in PAR1 ; so that qelements and I/O buffers are all out of PAR1 ; ;- .PSECT CODE,I,RO .ENABL LSB ZINIT:: .IF NE DBUG ; BIS #D.RTRC,DBGFLG ;Set flag to trace RT routines .ENDC ;NE DBUG MOV INFO+2,FREEPT ;Save pointer to free memory MOV INFO+2,END ; for memory allocation .DBG #D.RTRC,<"[ZINIT: FREEPT = END = %P]">,FREEPT ; ** ACTION ** This check need only be done for XM-like monitors MOV #<^o40000>,R0 ;R0 = Address beyond PAR1 space CMP INFO+2,R0 ;Does program reside in all of PAR1? BHIS 20$ ;Yes... .SETTO ;Nope, reserve rest of PAR1 CMP R0,#<^o40000> ;Were we able to? BEQ 10$ ;Yep... .MSG <"Insufficient memory"> ;Nope... we've got problems CALL ABORT ;Do some screen cleanup first JMP ZEXIT 10$: MOV R0,FREEPT ;Save pointer to free memory MOV R0,END ; for memory allocation .DBG #D.RTRC,<"[ZINIT: FREEPT = END = %P]">,FREEPT 20$: MOV #,R0 ;R0 = Space needed for extra Qelements CALL ZALLOC ;Allocate the space BCC 30$ ;Success... .MSG <"Insufficient space for extra Qelements"> CALL ABORT ;Do some screen cleanup first JMP ZEXIT 30$: MOV R0,RTQELM ;Save pointer to Qelement space .QSET R0,#RTQELN ;Tell RT about extra Qelement space .DBG #D.RTRC,<"[ZINIT: Qelement space at %P, size = %D. bytes]">,RTQELM,# .PRINT #RTNAME ;Announce ourself 40$: .GTLIN #RTIBUF,#RTFNMP ;Prompt the user for a game file BCC 50$ ;We got a response... .MSG <"Line too long"> BR 40$ 50$: TSTB RTIBUF ;Was there any real text? BEQ 40$ ;Nope, go reprompt ; ** ACTION ** Here we could do a scan of the input string for any ; wildcard characters and reject it if we find any... MOV SP,RTSPSV ;Save the stack pointer .CSISP #RTGSPC,#RTDTYP,#RTIBUF ;Parse the string and options BCC 60$ ;It parsed successfully... CALL RTCSIE ;Report what was wrong MOV RTSPSV,SP ;Restore the stack pointer BR 40$ 60$: MOV (SP)+,R1 ;R1 = Count of options to process BEQ 150$ ;There are none... ; Here we process the options which are on the stack 70$: MOV (SP)+,R0 ;Get an option and its flags MOV #RTSWTB,R2 ;R2 -> Table of options 80$: TSTB @R2 ;End of option processing table? BNE 90$ ;Nope... MOV RTSPSV,SP ;Restore stack pointer .MSG <"Invalid option"> BR 40$ 90$: CMPB R0,@R2 ;Does option match this entry? BEQ 100$ ;Yep... ADD #SW.ESZ,R2 ;Nope, on to next entry BR 80$ 100$: BITB #SW$DEF,SW.OFG(R2) ;Does option have a default value? BEQ 110$ ;Nope... MOV SW.ODF(R2),@SW.OAD(R2) ;Yes, set the default value 110$: TST R0 ;Did option come with value? BPL 120$ ;Nope... MOV (SP)+,@SW.OAD(R2) ;Yes, use the specified value BR 140$ ; and go check for another option 120$: BITB #SW$REQ,SW.OFG(R2) ;No, does it require one? BEQ 130$ ;Nope... .MSG <"Option value not specified"> MOV RTSPSV,SP BR 40$ 130$: MOV #1,@SW.OAD(R2) ;At least set the option non-zero 140$: DEC R1 ;More options to process? BGT 70$ ;Yep... ; Okay, options are processed and we know the name of the ; file. Let's open it and get this show on the road... 150$: .LOOKU #RTAREA,#RTGCHN,#RTISPC ;Open the file BCC 160$ ;Got it... CALL RTLOOE ;Failed... report why JMP 40$ 160$: MOV R0,RTGFSZ ;Save size of game file CALL INPEND ;Ensure the timer is not running BIS #,@#$JSW ;Set TT lower case, ; special mode and inhibit IO wait .RCTRL ;Make it take affect RETURN .DSABL LSB .PSECT DATA,D,RW RTQELM: .BLKW ; : Pointer to extra Qelement space RTGSPC: .BLKW ; : RT Game filespecs (from CSI) RTISPC = ; : First input file spec RTDTYP: .RAD50 /DAT/ ; : Default input file type .WORD 0,0,0 ; : Default output file types (none) RTGFSZ: .BLKW ; : Size of game file in blocks GAMINI:: RETURN .SBTTL ZBLK - Read a page from game file to memory ;+ ; ; ZBLK ; Reads some amount of the game file from disk into memory. ; ; Call: ; BADDR -> Where to put data read from file ; BPAGE = Block number to read ; BCNT = Byte count ; ; Returns: ; none ; ; Errors: ; o Any read errors are reported, and result in program ; termination ; ; Notes: ; o Since RT does reads in units of words, the specified ; byte count has to be rounded up to an even number of ; bytes and then converted to words. ; ;- .PSECT CODE,I,RO .ENABL LSB ZBLK:: .DBG #D.RTRC,<"[ZBLK: BADDR = %P, BPAGE = %D., BCNT = %D. bytes]">,BADDR,BPAGE,BCNT MOV R0,-(SP) ;Save a few registers for awhile MOV R1,-(SP) ; ... MOV BCNT,R1 ;R1 = Count of bytes INC R1 ;Convert to number of words ASR R1 ; rounded up to a word boundary .READW #RTAREA,#RTGCHN,BADDR,R1,BPAGE ;Synchronous read BCS 10$ ; In case of any errors... MOV (SP)+,R1 ;Restore previously saved registers MOV (SP)+,R0 ; ... RETURN 10$: .MSG <"Read error %B on block %U(%U) of game file">,@#$ERRBY,BPAGE,RTGFSZ .MSG <"Execution terminated"> CALL ABORT ;Do some screen cleanup first JMP ZEXIT .DSABL LSB .SBTTL SAVOPN - Create a game save file ;+ ; ; SAVOPN ; Create a file and open a channel to it for use in ; saving the status of a game. ; ; Call: ; R0 -> Filename ; R1 = length of filename ; ; Return: ; C-bit = 0, file is open on channel RTSCHN ; C-bit = 1, file could not be opened ; RTSBLK initialized to zero ; ; Note: ; No options are processed for the save/restore file ; ;- .PSECT CODE,I,RO .ENABL LSB SAVOPN:: .DBG #D.RTRC,<"[SAVOPN: Filename string at %P, length = %D. characters]">,R0,R1 MOV R0,-(SP) ;Save some registers for awhile MOV R1,-(SP) ; ... MOV R2,-(SP) ; ... MOV R0,R1 ;Save pointer to filename MOV SP,RTSPSV ;Save the stack pointer .CSISP #RTSSPC,#RTSTYP,R1 ;Parse the filename MOV RTSPSV,SP ;*C* Restore stack pointer BCC 10$ ;No errors... CALL RTCSIE ;Report what was wrong BR 30$ 10$: .ENTER #RTAREA,#RTSCHN,#RTOSPC,#-1 ;Try to create the file BCC 20$ ;Success... CALL RTENTE ;Report what was wrong BR 30$ 20$: CLR RTSBLK ;Start with block 0 CLC ;Return success (Carry reset) BR 40$ 30$: SEC ;Return failure (Carry set) 40$: MOV (SP)+,R2 ;Restore previously saved registers MOV (SP)+,R1 ; ... MOV (SP)+,R0 ; ... RETURN .DSABL LSB .PSECT DATA,D,RW RTSSPC: .BLKW ; : Parsed filespecs (from CSI) RTOSPC = ; : File spec for game save/restore ; Note, input file spec is used for input on RESxxx, and output file ; spec on SAVxxx RTSTYP: .RAD50 /ZSG/ ; : Default input file type .WORD 0,0,0 ; : Default output file types (none) RTSBLK: .BLKW ; : Save/restore block number .SBTTL SAVBLK - Write a block to the save file ;+ ; ; SAVBLK ; Write a block of data to the game save file ; ; Call: ; R0 -> 512-byte block to write ; ; Return: ; registers preserved ; RTSBLK updated ; ; Errors: ; possible, but not yet checked. ; ;- .PSECT CODE,I,RO .ENABL LSB SAVBLK:: .DBG #D.RTRC,<"[SAVBLK: buffer = %P, block = %D.]">,R0,RTSBLK MOV R0,-(SP) ;Save some registers for awhile MOV R1,-(SP) ; ... MOV R0,R1 ;Save pointer to filename .WRITW #RTAREA,#RTSCHN,R1,#256.,RTSBLK ;Write a block of data INC RTSBLK ;On to next block MOV (SP)+,R1 ;Restore previously saved registers MOV (SP)+,R0 ; ... RETURN .DSABL LSB .SBTTL SAVCLO - Close the game save file ;+ ; ; SAVCLO ; Close the game save file... ; ; Call: ; none ; ; Return: ; registers preserved ; ; Errors: ; possible, but not yet checked. ; ;- .PSECT CODE,I,RO .ENABL LSB SAVCLO:: .DBG #D.RTRC,<"[Entered SAVCLO]"> MOV R0,-(SP) ;Save some registers for awhile .CLOSE #RTSCHN ;Close the game save channel MOV (SP)+,R0 ;Restore previously saved register RETURN .DSABL LSB .SBTTL RESOPN - Open a game save file ;+ ; ; RESOPN ; Open a channel to a game save file in preparation ; to restore a game state. ; ; Call: ; R0 -> Filename ; R1 = length of filename ; ; Return: ; C-bit = 0, file is open on channel RTSCHN ; C-bit = 1, file could not be opened ; RTSBLK initialized to zero ; ; Note: ; No options are processed for the save/restore file ; ;- .PSECT CODE,I,RO .ENABL LSB RESOPN:: .DBG #D.RTRC,<"[RESOPN: Filename string at %P, length = %D. characters]">,R0,R1 MOV R0,-(SP) ;Save some registers for awhile MOV R1,-(SP) ; ... MOV R2,-(SP) ; ... MOV R0,R1 ;Save pointer to filename MOV SP,RTSPSV ;Save the stack pointer .CSISP #RTSSPC,#RTSTYP,R1 ;Parse the filename MOV RTSPSV,SP ;*C* Restore stack pointer BCC 10$ ;No errors... CALL RTCSIE ;Report what was wrong BR 30$ 10$: .LOOKU #RTAREA,#RTSCHN,#RTOSPC ;Try to open the file BCC 20$ ;Success... CALL RTLOOE ;Report what was wrong BR 30$ 20$: CLR RTSBLK ;Start with block 0 CLC ;Return success (Carry reset) BR 40$ 30$: SEC ;Return failure (Carry set) 40$: MOV (SP)+,R2 ;Restore previously saved registers MOV (SP)+,R1 ; ... MOV (SP)+,R0 ; ... RETURN .DSABL LSB .SBTTL RESBLK - Read a block from game save file ;+ ; ; RESBLK ; Read a block of data from the game save file ; ; Call: ; R0 -> 512-byte block to read ; ; Return: ; registers preserved ; RTSBLK updated ; ; Errors: ; possible, but not yet checked. ; ;- .PSECT CODE,I,RO .ENABL LSB RESBLK:: .DBG #D.RTRC,<"[RESBLK: buffer = %P, block = %D.]">,R0,RTSBLK MOV R0,-(SP) ;Save some registers for awhile MOV R1,-(SP) ; ... MOV R0,R1 ;Save pointer to filename .READW #RTAREA,#RTSCHN,R1,#256.,RTSBLK ;Read a block of data INC RTSBLK ;On to next block MOV (SP)+,R1 ;Restore previously saved registers MOV (SP)+,R0 ; ... RETURN .DSABL LSB .SBTTL RESCLO - Close the game save file ;+ ; ; RESCLO ; Close the game save file... ; ; Call: ; none ; ; Return: ; registers preserved ; ; Errors: ; possible, but not yet checked. ; ;- .PSECT CODE,I,RO .ENABL LSB RESCLO:: .DBG #D.RTRC,<"[Entered RESCLO]"> CALLR SAVCLO ;It does exactly the same thing... .DSABL LSB .SBTTL SCROPN - Open a scripting (log) file for output ;+ ; ; SCROPN ; Create a file and open a channel to it for use in ; logging the events in a game (a script) ; ; Call: ; R0 -> Filename, NUL-terminated ; R1 = length of filename, not including the NUL ; ; Return: ; C-bit = 0, file is open on channel RTLCHN ; C-bit = 1, file could not be opened ; RTLBLK initialized to zero ; ; Note: ; o No options are processed for the logging file ; o If a scripting file is open and another request comes in, ; the old file is closed. ; ;- .PSECT CODE,I,RO .ENABL LSB SCROPN:: .DBG #D.RTRC,<"[SCROPN: Filename string at %P, length = %D. characters]">,R0,R1 TST RTLOFG ;Is a scripting file already open? BNE 10$ ;Nope... CALL SCRCLO ;Yes, first close it 10$: MOV R0,-(SP) ;Save some registers for awhile MOV R1,-(SP) ; ... MOV R2,-(SP) ; ... MOV R0,R1 ;Save pointer to filename MOV SP,RTSPSV ;Save the stack pointer .CSISP #RTSSPC,#RTLTYP,R1 ;Parse the filename MOV RTSPSV,SP ;*C* Restore stack pointer BCC 20$ ;No errors... CALL RTCSIE ;Report what was wrong BR 40$ 20$: .ENTER #RTAREA,#RTLCHN,#RTOSPC,#-1 ;Try to create the file BCC 30$ ;Success... CALL RTENTE ;Report what was wrong BR 40$ 30$: CLR RTLBLK ;Start with block 0, MOV #RTLBF,RTLBP ; initialize buffer pointer CLR RTLCFG ; reset the dirty buffer flag CLR RTLOFG ; and flag file as available (open) CLC ;Return success (Carry reset) BR 50$ ;*C* 40$: SEC ;Return failure (Carry set) 50$: MOV (SP)+,R2 ;*C* Restore previously saved regs MOV (SP)+,R1 ;*C* ... MOV (SP)+,R0 ;*C* ... RETURN .DSABL LSB .PSECT DATA,D,RW ; Note, input file spec is used for output in SCRxxx routines RTLTYP: .RAD50 /LOG/ ; : Default input file type .WORD 0,0,0 ; : Default output file types (none) RTLBLK: .BLKW ; : Scripting (log) block number RTLBP: .BLKW ; : Scripting (log) buffer pointer RTLCFG: .BLKW ; : Scripting (log) dirty buffer flag RTLOFG: .WORD . ; ; Scripting (log) file open RTLBF: .BLKB 512. ; : Scripting (log) buffer RTLBFE = . .SBTTL SCRBLK - Write a line to the scripting file ;+ ; ; SCRBLK ; Write a line of text to the scripting (log) file ; ; Call: ; R0 -> String to output to log file, NUL terminated ; R1 = Length of string, not including NUL ; ; Return: ; registers preserved ; RTLBLK updated ; ; Errors: ; On any write errors, the file is closed and marked as ; unavailable. ; ;- .PSECT CODE,I,RO ; ** ACTION ** If a write fails and it is because we have reached ; end of file, we could close out the old file, reopen ; it, open a new copy which is slightly larger, copy ; all the data out of the old file to the new one, and ; continue logging. .ENABL LSB SCRBLK:: .DBG #D.RTRC,<"[SCRBLK: buffer = %P, length = %D.]">,R0,R1 TST RTLOFG ;Is the file still available? BNE 30$ ;Nope... MOV R0,-(SP) ;Save some registers for awhile MOV R1,-(SP) ; ... MOV R2,-(SP) ; ... MOV R0,R1 ;R1 -> String to be logged MOV RTLBP,R2 ;R2 -> Current position in buffer CALL 50$ ;Log the string BCS 10$ ;In case of write error MOV #RTCR,R1 ;R1 -> String to be logged () CALL 50$ ;Log the string BCS 10$ ;In case of write error MOV R2,RTLBP ;Keep track of updated buffer pointer BR 20$ 10$: CALL SCRCLO ;Close the file on any errors 20$: MOV (SP)+,R2 ;Restore previously saved registers MOV (SP)+,R1 ; ... MOV (SP)+,R0 ; ... CLC ;*C* BR 40$ ;*C* 30$: SEC ;*C* 40$: RETURN ;*C* ; The following subroutine moves the characters of a nul-terminated ; string to the log file buffer, writing a block of data when the ; buffer fills. After it has written a block, it resets the buffer ; pointer to the beginning of the block, but keeps track of the fact ; that the buffer is 'dirty'. When all the characters have been ; copied to the buffer, the remainder of the buffer is filled with ; nulls and the block is written. 50$: TSTB @R1 ;End of string? BEQ 60$ ;Yep... MOVB (R1)+,(R2)+ ;Not yet... move a character CMP R2,#RTLBFE ;Have we filled a block? BLO 50$ ;Not yet... .WRITW #RTAREA,#RTLCHN,#RTLBF,#256.,RTLBLK ;Write a block of data BCS 90$ ;*C* In case of error... INC RTLBLK ;Bump the block number, MOV #RTLBF,R2 ; reset buffer pointer, MOV SP,RTLCFG ; set the 'dirty buffer' flag BR 50$ ; and continue where we left off 60$: TST RTLCFG ;Is the buffer dirty? BEQ 80$ ;Nope... MOV R2,-(SP) ;Save current buffer position MOV R2,R0 ;Set to determine how full buffer is SUB #RTLBF,R0 ;R0 = Count of characters in buffer NEG R0 ;Set to determine count of dirty bytes ADD #512.,R0 ;R0 = Count of bytes to clean 70$: CLRB (R2)+ ;Clean a byte DEC R0 ;More to do? BGT 70$ ;Yep... MOV (SP)+,R2 ;All done, restore pointer CLR RTLCFG ;Reset the 'dirty buffer' flag 80$: .WRITW #RTAREA,#RTLCHN,#RTLBF,#256.,RTLBLK ;Ensure all data to be ; logged has been written ;;; BCS 90$ ;*C* In case of error... 90$: RETURN ;*C* .DSABL LSB .PSECT DATA,D,RW RTCR: .ASCII <15><12><0> ; .EVEN .SBTTL SCRCLO - Close the script (log) file ;+ ; ; SCRCLO ; Close the script (log) file ; ; Call: ; none ; ; Return: ; registers preserved ; ; Errors: ; possible, but not yet checked. ; ;- .PSECT CODE,I,RO .ENABL LSB SCRCLO:: .DBG #D.RTRC,<"[Entered SCRCLO]"> MOV R0,-(SP) ;Save some registers for awhile .CLOSE #RTLCHN ;Close the script (log) file MOV SP,RTLOFG ; and flag file as unavailable MOV (SP)+,R0 ;Restore previously saved register RETURN .DSABL LSB .SBTTL RTCSIE - Report various CSI errors ;+ ; ; RTCSIE ; This routine is called after a CSI error in order to ; report what the problem was with the string. ; ; Call: ; none ; ; Return: ; none ; ; Errors: ; none ; ;- .PSECT CODE,I,RO .ENABL LSB RTCSIE: MOV R0,-(SP) ;Save R0 for awhile MOVB @#$ERRBY,R0 ;Get the error byte BNE 10$ ;Not error 0 .MSG <"Invalid file specification"> BR 30$ 10$: CMPB R0,#1 ;Is it due to a device? BNE 20$ ;Nope... .MSG <"Specified device is unavailable"> BR 30$ ; ** NOTE ** ; We should never get to this code 20$: .MSG <"Unexpected error from CSI"> 30$: MOV (SP)+,R0 ;Restore R0 RETURN .DSABL LSB .SBTTL RTENTE - Report various .ENTER errors ;+ ; ; RTENTE ; This routine is called after a .ENTER error in order to ; report what the problem was. ; ; Call: ; none ; ; Return: ; none ; ; Errors: ; none ; ;- .PSECT CODE,I,RO .ENABL LSB RTENTE: MOV R0,-(SP) ;Save R0 for awhile MOVB @#$ERRBY,R0 ;Get the error byte BNE 10$ ;Not error 0 .MSG <"Channel is in use"> BR 70$ 10$: CMPB R0,#1 ;Insufficient space on volume? BNE 20$ ;Nope... .MSG <"Insufficient space on volume"> BR 70$ 20$: CMPB R0,#2 ;Non-shareable device? BNE 30$ ;Nope... .MSG <"Non-shareable device already in use"> BR 70$ 30$: CMPB R0,#3 ;Protected file BNE 40$ ;Nope... .MSG <"Protected file already exists"> BR 70$ 40$: CMPB R0,#4 ;FSN not found? BNE 50$ ;Nope... .MSG <"File sequence number not found"> BR 70$ 50$: CMPB R0,#5 ;FSN invalid or name is null BNE 60$ ;Nope... .MSG <"Invalid file sequence number, or filename is null"> BR 70$ ; ** NOTE ** ; We should never get to this code 60$: .MSG <"Unexpected error from .ENTER"> 70$: MOV (SP)+,R0 ;Restore R0 RETURN .DSABL LSB .SBTTL RTLOOE - Report various .LOOKUP errors ;+ ; ; RTLOOE ; This routine is called after a .LOOKUP error in order to ; report what the problem was. ; ; Call: ; none ; ; Return: ; none ; ; Errors: ; none ; ;- .PSECT CODE,I,RO .ENABL LSB RTLOOE: MOV R0,-(SP) ;Save R0 for awhile MOVB @#$ERRBY,R0 ;Get the error byte BNE 10$ ;Not error 0 .MSG <"Channel is in use"> BR 50$ 10$: CMPB R0,#1 ;Was the file found? BNE 20$ ;Nope... .MSG <"File not found"> BR 50$ 20$: CMPB R0,#2 ;Non-shareable device? BNE 30$ ;Nope... .MSG <"File already open on non-shareable device"> BR 50$ 30$: CMPB R0,#5 ;Was it an invalid argument? BNE 40$ ;Nope... .MSG <"Invalid argument"> BR 50$ ; ** NOTE ** We should never get to this code 40$: .MSG <"Unexpected error from .LOOKUP"> 50$: MOV (SP)+,R0 ;Restore R0 RETURN .DSABL LSB .SBTTL ZEXIT - Exits program ;+ ; ; ZEXIT - Exit program. ; ; Do all eventual cleanup here. ; ; This is called from all over the place. ; One might argue that we could start over after getting here, ; but currently we are expected to return to the OS... ; ;- .PSECT CODE,I,RO .ENABL LSB ZEXIT:: .DBG #D.RTRC,<"[Entered ZEXIT]"> ; ** ACTION ** If we ever have the code fetch/release handlers for ; the game file or save/restore file, we'll need to ; do the release here... CALL INPEND ;Turn off any read timer .CLOSE #RTSCHN ;Close channel to save/restore file .CLOSE #RTGCHN ;Close channel to game file .EXIT .DSABL LSB .SBTTL ZALLOC - Allocate memory ;+ ; ; ZALLOC ; Allocate additional memory (extend the program-available ; space). ; ; Call: ; R0 = Number of bytes to allocate ; ; Return: ; R0 -> Allocated memory ; ; Errors: ; C-bit = 1, unable to extend program ; ; Notes: ; If this routine returns an allocation failure (carry set), ; it will not be called again. ; ;- .PSECT CODE,I,RO .ENABL LSB ZALLOC:: .DBG #D.RTRC,<"[ZALLOC: Requested size = %D. bytes]">,R0 INC R0 ;Round up to an even number BIC #1,R0 ; of bytes (so we allocate full words) ADD FREEPT,R0 ;R0 = New desired high limit BCS 30$ ;In case it wraps ! MOV R0,-(SP) ;Save address we are asking for .SETTO ;'Please, Sir, may I have some more?' CMP R0,(SP)+ ;Did we get what we asked for? BLO 20$ ;Nope... MOV FREEPT,-(SP) ;Save old high limit... MOV R0,FREEPT ;Set new program high limit MOV R0,END ; ... .DBG #D.RTRC,<"[ZALLOC: FREEPT = END = %P]">,FREEPT MOV (SP)+,R0 ;R0 -> Allocated memory .DBG #D.RTRC,<"[ZALLOC: Memory allocated at %P]">,R0 CLC ;Return success (Carry=0) BR 30$ 20$: .DBG #D.RTRC,<"[ZALLOC: Insufficient memory]"> SEC ;Return failure (Carry=1) 30$: RETURN .DSABL LSB .SBTTL CHESIZ - Get cache page size ;+ ; ; CHESIZ ; Get the cache page size. ; ; Call: ; None ; ; Return: ; R0 -> Cache page size (in bytes) ; ; Errors: ; None ; ; Notes: ; The routine is called before starting to allocate cache, ; and can be used to do preparatory work before calls to ; CHEALL is done. ; ;- .PSECT CODE,I,RO .ENABL LSB CHESIZ:: MOV #512.,R0 ; We have a simple cache model. RETURN .DSABL LSB .SBTTL CHEALL - Allocate a cache page. ;+ ; ; CHEALL ; Allocate a cache page. ; ; Call: ; None ; ; Return: ; R0 -> Cache page identifier (used in CHEUPD) ; R1 -> Cache page address ; ; Errors: ; C-bit = 1, Not able to allocate a cache page. ; ; Notes: ; If this routine returns with carry set, it will not ; be called again. Game will start if it have succeeded ; atleast once. Otherwise program will abort with a message. ; ;- .PSECT CODE,I,RO .ENABL LSB CHEALL:: .ALLOC ; .ALLOC defaults to 512 bytes. MOV R0,R1 ; ID and address are the same. RETURN ; C-bit was preserved from .ALLOC .DSABL LSB .SBTTL CHEUPD - Update cache page ;+ ; ; CHEUPD ; Update cache page. Reads in the requested page from ; disk. ; ; Call: ; R0 -> Cache page identified ; R2,R3 -> Virtual address requested ; ; Return: ; R0 -> Relative address within cache page ; R2,R3 -> Virtual base address of page ; ; Errors: ; None ; ; Notes: ; The requested block is calculated and read in from disk. ; ;- .PSECT CODE,I,RO .ENABL LSB CHEUPD:: MOV R3,-(SP) ; Save address for offset calc. ASHC #-9.,R2 ; Calculate block #. .BLK R0,R3 ; Read in block (default is 512 bytes) ASHC #9.,R2 ; Get base address of page. MOV (SP)+,R0 ; Get virtual address. SUB R3,R0 ; Calculate offset from page start. RETURN .DSABL LSB .SBTTL GETSCL - Return screen width (columns) ;+ ; ; GETSCL ; Return screen width (number of columns) ; ; Call: ; none ; ; Returns: ; R0 = Screen width (columns) ; ; Errors: ; none ; ; Notes: ; RT-11 does not maintain much information on the type of ; terminals attached. It would take a fair amount of code ; to properly determine that, so we don't attempt to (yet). ; For the time-being, we'll have to use the current width ; setting (via SET TT WIDTH=n). ; ;- .PSECT CODE,I,RO .ENABL LSB GETSCL:: ; ** ACTION ** Maybe ZINIT should somehow determine what kind of ; terminal we're running on and build a table of this ; info... .GVAL #RTAREA,#$TCFIG ;Get address of terminal config info ;;; BIT #VRUNV$,@#$JSW ;Are we running virtually? ;;; BEQ 10$ ;Nope... MOV R0,-(SP) ;Yes, stack the address ; ** NOTE ** PEEK doesn't allow odd addresses. It is fortunate that ; the terminal width is the low byte of the word. ADD #$TTWID,@SP ; and build address of width info .PEEK #RTAREA,(SP)+ ;Get terminal width from low memory BR 20$ ;Join common code 10$: MOVB $TTWID(R0),R0 ;Nope, use the setting 20$: BIC #^C<377>,R0 ; (avoiding sign-extension) BNE 30$ ;Non-zero is okay... MOV #80.,R0 ;Default to standard DEC screen width 30$: .DBG #D.RTRC,<"[GETSCL: returning %D. columns]">,R0 RETURN .DSABL LSB .SBTTL GETSLN - Return screen length (lines) dbug = 1 ;+ ; ; GETSLN ; Return the screen length (number of lines) ; ; Call: ; none ; ; Return: ; R0 = Number of lines ; ; Errors: ; none ; ; Notes: ; RT-11 does not maintain much information on the type of ; terminals attached. It would take a fair amount of code ; to properly determine that, so we don't attempt to. At ; this time, we simply return the length of a standard ; DEC VT100 (and many other model video terminals) length ; of 24. ; ;- ; ** ACTION ** If not a scope-type terminal, what would be a reasonable ; value to return here? .PSECT CODE,I,RO .ENABL LSB GETSLN:: MOV #24.,R0 ;Default to VT100 screen length .DBG #D.RTRC,<"[GETSLN: returning %D. lines]">,R0 RETURN .DSABL LSB .SBTTL GETSTP - Return terminal type ;+ ; ; GETSTP ; Return a value indicating the terminal type. ; ; Call: ; none ; ; Return: ; R0 = Terminal type code ; ; Errors: ; none ; ; Notes: ; o RT-11 does not maintain much information on the type of ; terminals attached. It would take a fair amount of code ; to properly determine that, so we don't attempt to (yet). ; If the terminal is set SCOPE, we return VT100 as the type. ; If the terminal is set NOSCOPE, we return unknown. ; ; This can be over-ridden by the /T:n option on the command ; line. ; ;- .PSECT CODE,I,RO RTTTMX =: VT500 ;Must be last terminal type definition ; (found in VMAC) .IIF NDF TERMDF TERMDF = VT100 .ENABL LSB GETSTP:: MOV RTOPTT,R0 ;Was terminal type specified? BEQ 10$ ;Nope...(or was specified as zero) CMP R0,#RTTTMX ;Yes, is it within range? BLOS 50$ ;Yes... 10$: .GVAL #RTAREA,#$TCFIG ;Get pointer to terminal config info ;;; BIT #VRUNV$,@#$JSW ;Are we running virtually? ;;; BEQ 20$ ;Nope... MOV R0,-(SP) ;Stack the address ; ** ACTION ** This may not work on earlier versions .PEEK #RTAREA,(SP)+ ;Get terminal config from low memory BR 30$ 20$: MOV @R0,R0 ;R0 = Terminal config word 30$: BIT #BKSP$,R0 ;Are we set SCOPE? BNE 40$ ;Yep... MOV #UNKT,R0 ;No, return unknown type BR 50$ 40$: MOV #TERMDF,R0 ;Default to desired terminal type 50$: .DBG #D.RTRC,<"[GETSTP: returning terminal type %D.]">,R0 RETURN .DSABL LSB .PSECT DATA,D,RW RTOPTT: .BLKW ; : Terminal type option DBUG = 0 ; In case we are doing partial debug ;+ ; Missing routines added by Johnny Billquist for ZEMU/RT to just ; compile and run. ;- .PSECT CODE GETAVO:: GETSOF:: GETCOL:: CLC RETURN .END