mirror of
https://github.com/erkyrath/infocom-zcode-terps.git
synced 2026-01-11 23:43:24 +00:00
479 lines
9.9 KiB
Plaintext
479 lines
9.9 KiB
Plaintext
SUBTTL SYSIO - IBMPC SYSTEM ROUTINES
|
|
PAGE +
|
|
|
|
PUBLIC MCHRI,MTTYO,MCRLF,MSPRT,MINIT,MPRNT,MTIME,FINISH
|
|
;READ A CHARACTER INTO AX, WAITING UNTIL ONE IS AVAILABLE, NO ECHO
|
|
MCHRI PROC
|
|
PUSH CX
|
|
PUSH DX
|
|
CMP CHRFLG,0
|
|
JNZ MCHR1
|
|
MOV CHRFLG,1
|
|
MCHR1: MOV AH,CNOECHO ; (7u) USE NO ECHO
|
|
INT 21H
|
|
SUB AH,AH
|
|
POP DX
|
|
POP CX
|
|
RET
|
|
MCHRI ENDP
|
|
|
|
PUBLIC FEEP
|
|
FEEP PROC
|
|
MOV AX,7
|
|
CALL MTTYO ;BELL
|
|
RET
|
|
FEEP ENDP
|
|
|
|
;PRINT THE CHARACTER IN AL, FOREGROUND IN AH
|
|
MTTYO PROC
|
|
PUSH AX
|
|
PUSH BX ;SAVES
|
|
PUSH CX
|
|
PUSH DX
|
|
PUSH BP
|
|
PUSH SI ; (A0) TRASHED ANOTHER
|
|
PUSH AX
|
|
TEST VIDFLG,1 ; (A10) IS THE SCREEN DEVICE ENABLED?
|
|
JZ MTY00 ; (A10) ....NO
|
|
DEC AL ; (A0) SEE IF IT IS IMBEDDED HILITE
|
|
XOR AH,AH
|
|
CMP AX,0 ; (A0) ITS VALUE WOULD BE BETWEEN 0-MAX
|
|
JB MTY0
|
|
CMP AX,MAXHI
|
|
JA MTY0
|
|
MOV SI,OFFSET COLORS ; ++ OF HILIGHTS
|
|
CMP COLFLG,1 ; (A5) SHOULD WE USE COLOR TABLE?
|
|
JZ MTY0A ; (A9) ....YES
|
|
MOV SI,OFFSET HILITES ; (A9) ^ IBM TABLE
|
|
CMP IBMPC,1 ; (A9) SHOULD WE USE THE IBM TABLE?
|
|
JZ MTY0A ; (A9) ....YES
|
|
MOV SI,OFFSET NONIBM ; (A9) USE THE NONIBM MONO TABLE
|
|
MTY0A: SHL AL,1 ; (A0) IT IS, MULTIPLY BY TWO
|
|
MOV BX,AX ; (A0) GET AN INDEX INTO TABLE
|
|
MOV BX,[BX][SI] ; (A0) BX HAS OFFSET TO STRING
|
|
CALL MSPRT ; (A0) PRINT THE STRING
|
|
POP AX
|
|
JMP MTYO1 ; (A0) RESTORE ON EXIT
|
|
MTY0: INC AL
|
|
MOV AH,CCONIO
|
|
MOV DL,AL
|
|
INT 21H
|
|
MTY00: POP AX ; (A10) NEW ENTRYPOINT
|
|
TEST SCRFLG,1 ; (7x) IS SCRIPTING REQUESTED?
|
|
JZ MTYO1 ; (7n) IF NOT THEN DON'T BOTHER
|
|
CMP SCRHLD,1 ; (7n) IS SCRIPTING SUSPENDED?
|
|
JZ MTYO1
|
|
CALL PRTOUT
|
|
MTYO1: POP SI
|
|
POP BP
|
|
POP DX
|
|
POP CX
|
|
POP BX
|
|
POP AX
|
|
RET
|
|
MTTYO ENDP
|
|
|
|
;PRINT A CARRIAGE RETURN/LINE FEED WITH MORE MODE
|
|
MCRLF PROC
|
|
PUSH AX ;SAVES
|
|
PUSH BX
|
|
PUSH CX
|
|
PUSH DX
|
|
PUSH BP
|
|
TEST VIDFLG,1 ; (A14) SCREEN DEVICE ON?
|
|
JZ MCR1 ; (A14) SKIP SCREEN SCROLL
|
|
TEST SCROLL,1 ;(7) WHAT KIND OF SCROLLING
|
|
JNZ MCR$
|
|
TEST SCRNFLG,1 ; (7) ARE WE IN SCREEN #1
|
|
JNZ MCR$ ; (7) YES, USE OLD SCROLL
|
|
MOV AH,SCROLLUP ;(7) USE A VIDEO BIOS SCROLL
|
|
MOV AL,1 ;(7) ONLY 1 LINE
|
|
MOV CX,TOPLIN ;(7) ALWAYS FREEZE TOP LINE
|
|
MOV DX,184FH ; (A0) USE CONSTANT
|
|
MOV BH,SCRATR ;(7) GET THE SCREEN ATTRIBUTE
|
|
INT 10H ;(7) CALL THE VIDEO
|
|
MCR$: MOV AH,CCONIO
|
|
MOV DL,13
|
|
INT 21H
|
|
TEST SCRNFLG,1 ; (7) ARE WE WRITING TO WINDOW 1
|
|
JNZ MCRA$
|
|
TEST SCROLL,1 ;(7) NO LINE FEED ON WINDOWED SCROLL
|
|
JZ NOLF
|
|
MCRA$: MOV AH,CCONIO
|
|
MOV DL,10
|
|
INT 21H
|
|
NOLF: TEST SCRNFLG,1 ;(7) NO MORE FOR WINDOW 1
|
|
JNZ MCR1 ;(7) SKIP THIS GARBAGE
|
|
INC MORLIN ;INCREMENT NUMBER OF LINES OUTPUT
|
|
MOV AL,SLPP
|
|
SUB AH,AH
|
|
DEC AX ;(7n) SO THAT STATUS LINE DOESN'T OVERWRITE
|
|
MCRB$: MOV DX,TOPLIN ;(7) GET SCROLLING WINDOW TOPLINE
|
|
XCHG DH,DL ;(7) SCROLL LINE IN DL
|
|
SUB AL,DL ;(7) THIS MANY LINES NOW
|
|
CMP MORLIN,AX
|
|
JL MCR1
|
|
MOV MORLIN,0
|
|
MOV SCRHLD,1 ; (7o) SUSPEND SCRIPT
|
|
PRINT MORE
|
|
CALL MCHRI
|
|
PRINT EMORE
|
|
MOV SCRHLD,0 ; (7o) RESUME SCRIPT
|
|
MCR1: TEST SCRFLG,1 ; (7x) CHANGED TO TEST
|
|
JZ MCR2
|
|
CALL PRTCRL
|
|
;(E0) REMOVE THIS
|
|
; OR WORD PTR ES:[PFLAGS],REFRESH ;(A17)REFRESH THE STATUS LINE
|
|
MCR2: POP BP
|
|
POP DX
|
|
POP CX
|
|
POP BX
|
|
POP AX
|
|
RET
|
|
MCRLF ENDP
|
|
|
|
|
|
MSPRT PROC
|
|
MOV CL,BYTE PTR [BX]
|
|
SUB CH,CH
|
|
CMP CL,0
|
|
JE MSPRT1
|
|
MSPLP: INC BX
|
|
MOV DL,BYTE PTR [BX]
|
|
MOV AH,06H
|
|
PUSH BX
|
|
INT 21H
|
|
POP BX
|
|
LOOP MSPLP
|
|
MSPRT1: RET
|
|
MSPRT ENDP
|
|
|
|
MINIT PROC
|
|
MINIT1: MOV BX,OFFSET STINIT
|
|
TEST COLFLG,1 ;(7) ARE WE IN COLOR MODE
|
|
JZ MINIT2 ;(7)
|
|
MOV BX,OFFSET CTINIT ;(7)
|
|
MINIT2: CALL MSPRT
|
|
RET
|
|
MINIT ENDP
|
|
|
|
;PRINT A STRING, POINTER (TO DATA SEGMENT) IN AX, WHITE FOREGROUND
|
|
MPRNT PROC
|
|
|
|
; (A10) SECTION COMMENTED OUT
|
|
; CMP GAMEIN,1 ; (7q)DO NOT CHECK THIS UNLESS THE GAME IS IN
|
|
; JNZ MPR0
|
|
; PUSH AX
|
|
; MOV AX,ES:[PFLAGS] ; (7n) SCRIPTING?
|
|
; XCHG AH,AL ; (7n) SWAP BYTES
|
|
; MOV SCRFLG,AL ; (7n) TURN IT ON, TURN IT ON AGAIN!
|
|
; POP AX
|
|
|
|
MPR0: PUSH BX ;SAVE BX
|
|
MOV BX,AX ;STRING POINTER
|
|
MPR1: MOV AL,[BX] ;GET NEXT CHARACTER
|
|
CMP AL,0 ;END OF LINE, WITH CRLF?
|
|
JE MPR2 ;YES
|
|
CMP AL,80H ;END OF LINE, NO CRLF?
|
|
JE MPR3 ;YES
|
|
CALL MTTYO ;PRINT CHARACTER
|
|
INC BX ;POINT TO NEXT CHARACTER
|
|
JMP MPR1 ;REPEAT
|
|
MPR2: CALL MCRLF ;PRINT A CRLF
|
|
MPR3: POP BX ;RESTORE BX
|
|
RET
|
|
MPRNT ENDP
|
|
|
|
;
|
|
; GET TIME AND USE IT TO SEED THE RANDOM NUMBER GENERATOR
|
|
;
|
|
|
|
MTIME PROC
|
|
PUSH CX ; SAVE REGISTERS
|
|
PUSH DX
|
|
MOV AH,CTIME ; GET TIME OF DAY
|
|
INT 21H
|
|
CMP CX,0 ; (LD1) IF NO CLOCK TIME
|
|
JNE MTIME0 ; (LD1) IS, SO OK
|
|
MOV RSEED1,08D0EH ; (LD1) USE A NUMBER
|
|
MOV RSEED2,09F81H ; (LD1) I JUST MADE UP SO NOT 0
|
|
JMP MTIME1 ; (LD1) DOES'NT MATTER, ONLY COMES HERE ONCE
|
|
MTIME0: MOV RSEED1,CX ; HOURS & MINUTES
|
|
MOV RSEED2,DX ; SECONDS & 100THS
|
|
MTIME1: POP DX ; RESTORE REGISTERS
|
|
POP CX
|
|
RET
|
|
MTIME ENDP
|
|
|
|
; ------------------------
|
|
; INITIALIZE SPEAKER TIMER
|
|
; ------------------------
|
|
;
|
|
; PURPOSE: THIS ROUTINE INITIALIZES THE PORTION OF THE 8253 TIMER
|
|
; CHIP USED BY THE SPEAKER SYSTEM. IN PARTICULAR, IT SETS
|
|
; UP CHANNEL 2 OF THE TIMER AS A SQUARE-WAVE GENERATOR.
|
|
;
|
|
; *** NOTE *** THIS ROUTINE IS TO BE CALLED DURING COLD START
|
|
;
|
|
; INPUTS: NONE
|
|
;
|
|
; OUTPUTS: TIMER 2
|
|
;
|
|
; REGISTERS DESTROYED: NONE
|
|
;
|
|
; EXTERNAL REFERENCES: NONE
|
|
;
|
|
|
|
PUBLIC INITSND
|
|
INITSND PROC
|
|
PUSH AX ;(A0) SAVE REGISTERS
|
|
MOV AL,TMRCWD ;(A0) GET TIMER CONTROL WORD
|
|
OUT TMRCPT,AL ;(A0) SEND IT TO THE CONTROL PORT
|
|
POP AX ;(A0) RESTORE REGISTERS
|
|
RET
|
|
INITSND ENDP
|
|
|
|
; ----------------------
|
|
; SET THE TONE FREQUENCY
|
|
; ----------------------
|
|
;
|
|
; PURPOSE: THIS ROUTINE SELECTS THE FREQUENCY OF THE SQUARE-WAVE
|
|
; TONE TO THE SPEAKER.
|
|
;
|
|
; INPUTS: CX=FREQUENCY
|
|
;
|
|
; OUTPUTS: TIMER 2
|
|
;
|
|
; REGISTERS DESTROYED: NONE
|
|
;
|
|
; EXTERNAL REFERENCES: NONE
|
|
;
|
|
|
|
PUBLIC TONESET
|
|
TONESET PROC
|
|
PUSH AX ;(A0) SAVE REGISTERS
|
|
PUSH CX
|
|
MOV AL,CL ;(A0) GET LOWER BYTE
|
|
OUT TMRDPT,AL ;(A0) SEND OUT VALUE TO TIMER
|
|
MOV AL,CH ;(A0) GET UPPER BYTE
|
|
OUT TMRDPT,AL ;(A0) SEND OUT VALUE TO TIMER
|
|
POP CX ;(A0) RESTORE REGISTERS
|
|
POP AX
|
|
RET
|
|
TONESET ENDP
|
|
|
|
; ------------
|
|
; TURN ON TONE
|
|
; ------------
|
|
;
|
|
; PURPOSE: THIS ROUTINE TURNS ON THE TIMER AND SPEAKER TO PRODUCE
|
|
; A TONE. THE FREQUENCY OF THE TONE MUST HAVE ALREADY
|
|
; BEEN SENT TO THE TIMER.
|
|
;
|
|
; INPUTS: NONE
|
|
;
|
|
; OUTPUTS: TIMER 2, AND SPEAKER
|
|
;
|
|
; REGISTERS DESTROYED: NONE
|
|
;
|
|
; EXTERNAL REFERENCES: NONE
|
|
;
|
|
|
|
PUBLIC TONEON
|
|
TONEON PROC
|
|
PUSH AX ;(A0) SAVE REGISTERS
|
|
IN AL,PTBCPT ;(A0) GET SYSTEM PORT B CONTROL DATA
|
|
OR AL,SPKRON ;(A0) TURN SPEAKER AND TIMER ON
|
|
OUT PTBCPT,AL ;(A0) SEND OUT NEW VALUE
|
|
POP AX ;(A0) RESTORE REGISTERS
|
|
RET
|
|
TONEON ENDP
|
|
|
|
; ------------
|
|
; TURN OFF TONE
|
|
; ------------
|
|
;
|
|
; PURPOSE: THIS ROUTINE TURNS OFF THE TIMER AND SPEAKER
|
|
;
|
|
; INPUTS: NONE
|
|
;
|
|
; OUTPUTS: TIMER 2, AND SPEAKER
|
|
;
|
|
; REGISTERS DESTROYED: NONE
|
|
;
|
|
; EXTERNAL REFERENCES: NONE
|
|
;
|
|
|
|
PUBLIC TONEOFF
|
|
TONEOFF PROC
|
|
PUSH AX ;(A0) SAVE REGISTERS
|
|
IN AL,PTBCPT ;(A0) GET SYSTEM PORT B CONTROL DATA
|
|
AND AL,SPKROFF ;(A0) TURN SPEAKER AND TIMER OFF
|
|
OUT PTBCPT,AL ;(A0) SEND OUT NEW VALUE
|
|
POP AX ;(A0) RESTORE REGISTERS
|
|
RET
|
|
TONEOFF ENDP
|
|
|
|
; -----
|
|
; DELAY
|
|
; -----
|
|
;
|
|
; PURPOSE: THIS ROUTINE DELAYS FOR A SPECIFIED NUMBER OF .05 SEC
|
|
; INTERVALS.
|
|
;
|
|
; INPUTS: [CX] = NUMBER OF .05 SEC TO DELAY
|
|
;
|
|
; OUTPUTS: NONE
|
|
;
|
|
; REGISTERS DESTROYED: NONE
|
|
;
|
|
; EXTERNAL REFERENCES: NONE
|
|
;
|
|
|
|
PUBLIC DELAY,DELAY1,DELAY2
|
|
DELAY PROC
|
|
PUSH AX ;(A0) SAVE REGISTERS
|
|
PUSH BX
|
|
PUSH CX
|
|
PUSH DX
|
|
|
|
CALL SYNCH ;(A0) SYNCHRONIZE TIMER
|
|
MOV TIMER,DL ;(A0) SAVE 1/100 SEC COUNT
|
|
|
|
; TIMING LOOP
|
|
DELAY1: PUSH CX ;(A0) SAVE LOOP COUNTER
|
|
DELAY2: MOV AH,CTIME ;(A0) GET THE TIME UNTIL IT CHANGES
|
|
INT 21H ;(A0) MSDOS FUNCTION CALL
|
|
CMP DL,TIMER ;(A0) HAS THE CLOCK TICKED?
|
|
JNZ DELAY3 ; YES, GO DO COUNTDOWN
|
|
CMP DL,0 ; NO, BUT IF NOT STUCK AT 0
|
|
JNZ DELAY2 ; WAIT FOR IT TO TICK
|
|
POP CX ; CLEAN UP STACK
|
|
JMP DELAY4 ; AND LEAVE
|
|
DELAY3: MOV TIMER,DL ;(A0) SAVE NEW COUNT
|
|
POP CX ; GET LOOP COUNTER BACK
|
|
LOOP DELAY1 ;(A0) AND LOOP
|
|
|
|
DELAY4: POP DX ;(A0) RESTORE REGISTERS
|
|
POP CX
|
|
POP BX
|
|
POP AX
|
|
RET
|
|
DELAY ENDP
|
|
|
|
; -----
|
|
; SYNCH
|
|
; -----
|
|
;
|
|
; PURPOSE: THIS ROUTINE WAITS FOR A CHANGE IN THE 1/100 SEC TIMER, TO
|
|
; INSURE THAT WE'RE AT THE START OF A NEW TIME PERIOD.
|
|
;
|
|
; INPUTS: NONE
|
|
;
|
|
; OUTPUTS: [DL] = 1/100 SEC COUNT AT SYNCH TIME
|
|
;
|
|
; REGISTERS DESTROYED: DL
|
|
;
|
|
; EXTERNAL REFERENCES: NONE
|
|
;
|
|
|
|
PUBLIC SYNCH,SYNCH1
|
|
SYNCH PROC
|
|
PUSH AX ;(A0) SAVE REGISTERS
|
|
PUSH BX
|
|
PUSH CX
|
|
MOV AH,CTIME ;(A0) GET THE TIME FROM THE REAL TIME CLOCK
|
|
INT 21H ;(A0) MSDOS FUNCTION CALL
|
|
MOV TIMER,DL ;(A0) SAVE 1/100 SEC COUNT
|
|
|
|
; SYNCHRONIZE
|
|
SYNCH1: MOV AH,CTIME ;(A0) GET THE TIME AGAIN, SO WE CAN INSURE
|
|
INT 21H ;(A0) THAT WE ARE SYNCHRONIZED WITH THE
|
|
CMP DL,TIMER ;(A0) START OF A NEW TIMING PERIOD
|
|
JNZ SYNCH2 ; CLOCK TICKED, SO WIN
|
|
CMP DL,0 ; CLOCK DIDN'T TICK, AND IS 0, SO QUIT
|
|
JNZ SYNCH1 ; HACK TO PREVENT LOOPS WHEN 1/100'S
|
|
; CLOCK ISN'T WORKING
|
|
SYNCH2: POP CX ;(A0) RESTORE REGISTERS
|
|
POP BX
|
|
POP AX
|
|
RET
|
|
SYNCH ENDP
|
|
|
|
; ----
|
|
; FREQ
|
|
; ----
|
|
;
|
|
; PURPOSE: THIS ROUTINE CONVERTS A FREQUENCY TO THE NUMBER REQUIRED
|
|
; BY TONESET.
|
|
;
|
|
; INPUTS: [CX] = FREQUENCY IN HZ
|
|
;
|
|
; OUTPUTS: [CX] = CONVERTED VALUE
|
|
;
|
|
; REGISTERS DESTROYED: CX
|
|
;
|
|
; EXTERNAL REFERENCES: NONE
|
|
;
|
|
|
|
PUBLIC FREQ
|
|
FREQ PROC
|
|
PUSH AX ;(A0) SAVE REGISTERS
|
|
PUSH BX
|
|
PUSH DX
|
|
|
|
; DIVIDE FREQUENCY BY 1193182
|
|
MOV DX,12H ;(A0) UPPER PART OF NUMERATOR
|
|
MOV AX,34DEH ;(A0) LOWER PART OF NUMERATOR
|
|
DIV CX ;(A0) DIVIDE BY FREQUENCY
|
|
MOV CX,AX ;(A0) QUOTIENT IS THE OUTPUT
|
|
POP DX ;(A0) RESTORE REGISTERS
|
|
POP BX
|
|
POP AX
|
|
RET
|
|
FREQ ENDP
|
|
|
|
; -----------
|
|
; MAKE A TONE
|
|
; -----------
|
|
;
|
|
; PURPOSE: THIS ROUTINE MAKES A TONE OF A GIVEN FREQUENCY AND LENGTH
|
|
;
|
|
; INPUTS: [CX] = FREQUENCY IN HZ
|
|
; [DX] = DURATION IN .05 SEC
|
|
;
|
|
; OUTPUTS: TO THE SPEAKER AND TIMER 2
|
|
;
|
|
; REGISTERS DESTROYED: NONE
|
|
;
|
|
; EXTERNAL REFERENCES: {TONESET}, {TONEON}, {TONEOFF}, {DELAY}
|
|
;
|
|
|
|
PUBLIC TONE
|
|
TONE PROC
|
|
PUSH AX ;(A0) SAVE REGISTERS
|
|
PUSH BX
|
|
PUSH CX
|
|
PUSH DX
|
|
|
|
; COMPUTE THE FREQUENCY AND SETUP THE TONE GENERATOR (TIMER 2)
|
|
CALL FREQ ;(A0) CONVERT THE FREQUENCY
|
|
CALL TONESET ;(A0) SET UP TIMER 2
|
|
|
|
; TURN ON THE TONE
|
|
CALL TONEON
|
|
|
|
; WAIT FOR THE DELAY TIME
|
|
MOV CX,DX
|
|
CALL DELAY
|
|
|
|
; TURN OFF THE TONE
|
|
CALL TONEOFF
|
|
|
|
POP DX ;(A0) RESTORE THE REGISTERS
|
|
POP CX
|
|
POP BX
|
|
POP AX
|
|
RET
|
|
TONE ENDP
|