Category : A Collection of Games for DOS and Windows
Archive   : EMPIREU.ZIP
Filename : CONSOLE.ASM

 
Output of file : CONSOLE.ASM contained in archive : EMPIREU.ZIP
TITLE CONSOLE for EMPIRE MONITOR

PAGE 44,132

PUBLIC CONSOLE_INTERFACE_UNIT

DATA SEGMENT PUBLIC

CR EQU 13 ; carriage-return
LF EQU 10 ; line-feed
NLPS EQU 25 ; number of lines per screen

EMEPFP DB 13,10,'Error positioning file pointer',13,10,'$'
EMERF DB 13,10,'Error reading',13,10,'$'
EMUOF DB 13,10,'Unable to open file',13,10,'$'

XK_DOWN DB 0,80 ; extended key code: down arrow
XK_END DB 0,79 ; extended key code: End
XK_HOME DB 0,71 ; extended key code: Home
XK_PGDN DB 0,81 ; extended key code: PgDn
XK_PGUP DB 0,73 ; extended key code: PgUp
XK_UP DB 0,72 ; extended key code: up arrow

AFBNOS DD ? ; address of first byte not on screen
AFBOS DD ? ; address of first byte on screen

BUFSIZ EQU 2050 ; most bytes that can be displayed
BUF DB BUFSIZ DUP (?)
BUFCNT DW ? ; number of bytes in buffer

LOGHNDL DW ? ; handle attached to log file

ORIG_SCREEN DW 2000 DUP (?) ; contents of screen when started

PAGEBEG DW ? ; offset of first byte of current page
PAGEHGT DW ? ; number of full lines in current page
PAGELEN DW ? ; number of bytes in current page

SROFF DW ? ; screen RAM offset
SRSEG DW ? ; screen RAM segment

DATA ENDS

CODE SEGMENT PUBLIC

ASSUME CS : CODE
ASSUME DS : DATA

EXTRN TRUEDOS : NEAR

CONSOLE_INTERFACE_UNIT PROC ; Console interface for EMPIRE
; MONITOR
; BX = handle attached to log file
PUSH AX
PUSH DS

MOV AX,DATA
MOV DS,AX

MOV LOGHNDL,BX

CALL SCREEN_INIT
CALL READ_LAST_PAGE
CIU_ONE_MORE_TIME:
CALL PPAGE ; put page on screen
CALL GCHAR ; get some response
CMP AL,27
JZ CIU_FINISHED_DISPLAYING
CALL DO_AS_TOLD
JMP CIU_ONE_MORE_TIME

CIU_FINISHED_DISPLAYING:

CIU_EXIT:
CALL SCREEN_TERM ; restore screen

POP DS
POP AX
RET
CONSOLE_INTERFACE_UNIT ENDP


DO_AS_TOLD PROC ; Perform indicated action
; AL = character primary
; AH = character secondary
CMP AX,WORD PTR XK_HOME
JZ DAT_HOME
CMP AX,WORD PTR XK_PGUP
JZ DAT_PGUP
CMP AX,WORD PTR XK_END
JZ DAT_END
CMP AX,WORD PTR XK_PGDN
JZ DAT_PGDN
JMP DAT_EXIT

DAT_HOME:
CALL READ_FIRST_PAGE
JMP DAT_EXIT

DAT_PGUP:
CALL READ_PREV_PAGE
JMP DAT_EXIT

DAT_END:
CALL READ_LAST_PAGE
JMP DAT_EXIT

DAT_PGDN:
CALL READ_NEXT_PAGE
JMP DAT_EXIT

DAT_EXIT:
RET
DO_AS_TOLD ENDP


ERASE PROC ; Erase screen
comment |
PUSH AX
MOV AL,27
CALL PCHAR
MOV AL,'['
CALL PCHAR
MOV AL,'2'
CALL PCHAR
MOV AL,'J'
CALL PCHAR
POP AX
|
PUSH AX
PUSH CX
PUSH DI
PUSH ES
MOV ES,SRSEG
MOV DI,0
MOV CX,2000
MOV AX,0720H
REP STOSW
MOV SROFF,0
POP ES
POP DI
POP CX
POP AX
RET
ERASE ENDP


FIND_FIRST_PAGE PROC ; Locate first screen's worth in
; current buffer
; Sets PAGEBEG, PAGEHGT, PAGELEN
; & AFBNOS
PUSH AX
PUSH CX
PUSH DX
PUSH SI
; page definitely starts at beginning of buffer
MOV SI,OFFSET BUF
MOV PAGEBEG,SI
; now try to find enough end-of-lines to fill the screen
MOV CX,BUFCNT
MOV DX,NLPS
JCXZ FFP_FOUND_IT
DEC SI
FFP_CHECK_NEXT:
; we're definitely displaying this byte
INC SI
DEC CX
; if it's the last byte, we're done
JZ FFP_FOUND_IT
; otherwise, if it's a line-feed...
CMP BYTE PTR [SI],LF
JNZ FFP_CHECK_NEXT
; ...and we've found enough line-feeds...
DEC DX
JNZ FFP_CHECK_NEXT
; ...we're done
FFP_FOUND_IT:
; number of bytes in page is number of bytes we considered
SUB CX,BUFCNT
NEG CX
MOV PAGELEN,CX
; number of full lines in page is number of end-of-lines
; we found
SUB DX,NLPS
NEG DX
MOV PAGEHGT,DX
; first byte not on screen is that many bytes past first
; byte on screen
MOV AX,WORD PTR AFBOS
MOV DX,WORD PTR AFBOS+2
ADD AX,CX
ADC DX,0
MOV WORD PTR AFBNOS ,AX
MOV WORD PTR AFBNOS+2,DX

POP SI
POP DX
POP CX
POP AX
RET
FIND_FIRST_PAGE ENDP


FIND_LAST_PAGE PROC ; Locate last screen's worth in
; current buffer
; Sets PAGEBEG, PAGEHGT, PAGELEN
; & AFBOS
; locate first byte to display on screen if intend to
; display last byte of buffer
PUSH AX
PUSH CX
PUSH DX
PUSH SI
MOV DX,NLPS ; we want enough lines to fill the
; screen
; provided there's anything in the buffer
MOV CX,BUFCNT
JCXZ FLP_FOUND_IT
; start with last byte of buffer
MOV SI,OFFSET BUF
ADD SI,CX
DEC SI
FLP_CHECK_NEXT:
DEC SI ; if there's another byte...
DEC CX
JCXZ FLP_FOUND_IT
CMP BYTE PTR [SI],LF ; ...line-feed ends previous line
JNZ FLP_CHECK_NEXT
DEC DX ; if need more lines...
JNZ FLP_CHECK_NEXT ; ...keep looking
FLP_FOUND_IT:
; CX is index (1..BUFCNT) of last byte in front of page
; SI is offset of that byte
INC SI ; point to first byte to display
MOV PAGEBEG,SI
SUB CX,BUFCNT ; compute number of bytes to be
NEG CX ; displayed
MOV PAGELEN,CX
; number of full lines in page is number of end-of-lines
; we counted
SUB DX,NLPS
NEG DX
MOV PAGEHGT,DX
; compute address of first byte on screen
MOV AX,WORD PTR AFBNOS
MOV DX,WORD PTR AFBNOS+2
SUB AX,CX
SBB DX,0
MOV WORD PTR AFBOS ,AX
MOV WORD PTR AFBOS+2,DX
POP SI
POP DX
POP CX
POP AX
RET
FIND_LAST_PAGE ENDP


GCHAR PROC ; Get character from keyboard
; returns AL = character primary
; AH = character secondary
MOV AH,0
INT 16H
RET
GCHAR ENDP

PCHAR PROC ; Put character to screen
; AL = character
PUSH AX
PUSH DX
MOV DL,AL
MOV AH,2
CALL TRUEDOS
POP DX
POP AX
RET
PCHAR ENDP

PPAGE PROC ; Put one page to screen
PUSH AX
PUSH BX
PUSH CX
PUSH DI
PUSH DX
PUSH ES
PUSH SI
CALL ERASE
MOV SI,PAGEBEG
MOV CX,PAGELEN
JCXZ PPAGE_EXIT
MOV ES,SRSEG
MOV DI,0
MOV AH,07
MOV DX,79 ; watch out for line overrun
PPAGE_PUT_NEXT:
LODSB
; ignore carriage-returns
CMP AL,CR
JZ PPAGE_READY_FOR_NEXT
; treat line-feed as newline
CMP AL,LF
JNZ PPAGE_STORE_IT
PUSH AX
MOV AX,DI
MOV DX,0
MOV BX,160 ; bytes per line of screen RAM
DIV BX ; AX = full lines before current position
INC AX ; advance to next line
MUL BX
MOV DI,AX
POP AX
MOV DX,79
JMP PPAGE_READY_FOR_NEXT
PPAGE_STORE_IT:
CMP DX,0 ; don't allot too many to one line
JZ PPAGE_READY_FOR_NEXT
STOSW
DEC DX
PPAGE_READY_FOR_NEXT:
LOOP PPAGE_PUT_NEXT
PPAGE_EXIT:
POP SI
POP ES
POP DX
POP DI
POP CX
POP BX
POP AX
RET
PPAGE ENDP

READ_FIRST_PAGE PROC ; Read first page of file
; returns Carry if error
PUSH AX
PUSH BX
PUSH CX
PUSH DX

; read enough starting with first byte of file to
; guarantee having a screen's worth

; position to beginning of file
MOV DX,0
MOV CX,0
MOV WORD PTR AFBOS ,DX
MOV WORD PTR AFBOS+2,CX
MOV BX,LOGHNDL
MOV AH,42H ; position file read/write pointer
MOV AL,0 ; absolute position
CALL TRUEDOS
JNC RFP_POSITIONED
MOV AH,9
MOV DX,OFFSET EMEPFP
CALL TRUEDOS
STC
JMP RFP_EXIT
RFP_POSITIONED:
MOV AH,3FH ; read
MOV CX,BUFSIZ
MOV DX,OFFSET BUF
CALL TRUEDOS
JNC RFP_BUFFER_READ
MOV AH,9
MOV DX,OFFSET EMERF
CALL TRUEDOS
STC
JMP RFP_EXIT
RFP_BUFFER_READ:
MOV BUFCNT,AX
; position within buffer to display first screen's worth
CALL FIND_FIRST_PAGE
RFP_EXIT:
POP DX
POP CX
POP BX
POP AX
RET
READ_FIRST_PAGE ENDP

READ_LAST_PAGE PROC ; Read last page of file
; returns Carry if error
PUSH AX
PUSH BX
PUSH CX
PUSH DX
; set position pointer to end-of-file
MOV AH,42H ; position read/write pointer
MOV AL,2 ; to end-of-file
MOV BX,LOGHNDL
MOV CX,0 ; plus two-word offset
MOV DX,0
CALL TRUEDOS
JNC RLP_POSITIONED
MOV AH,9
MOV DX,OFFSET EMEPFP
CALL TRUEDOS
STC
JMP RLP_EXIT
RLP_POSITIONED:
MOV WORD PTR AFBOS ,AX
MOV WORD PTR AFBOS+2,DX
; having lied that first byte on screen is first byte
; after file, last page of file is previous page
CALL READ_PREV_PAGE
RLP_EXIT:
POP DX
POP CX
POP BX
POP AX
RET
READ_LAST_PAGE ENDP


READ_NEXT_PAGE PROC ; Read page after current page
PUSH AX
PUSH BX
PUSH CX
PUSH DX

; read enough starting with first byte to be displayed to
; guarantee having a screen's worth

; position to desired point
MOV DX,WORD PTR AFBNOS
MOV CX,WORD PTR AFBNOS+2
MOV WORD PTR AFBOS ,DX
MOV WORD PTR AFBOS+2,CX
MOV BX,LOGHNDL
MOV AH,42H ; position file read/write pointer
MOV AL,0 ; absolute position
CALL TRUEDOS
JNC RNP_POSITIONED
MOV AH,9
MOV DX,OFFSET EMEPFP
CALL TRUEDOS
STC
JMP RNP_EXIT
RNP_POSITIONED:
MOV AH,3FH ; read
MOV CX,BUFSIZ
MOV DX,OFFSET BUF
CALL TRUEDOS
JNC RNP_BUFFER_READ
MOV AH,9
MOV DX,OFFSET EMERF
CALL TRUEDOS
STC
JMP RNP_EXIT
RNP_BUFFER_READ:
MOV BUFCNT,AX
; position within buffer to display first screen's worth
CALL FIND_FIRST_PAGE
; if we have a full screen's worth, we're happy
CMP PAGEHGT,NLPS
JZ RNP_EXIT
; since there was less than a full screen's worth when we
; started with the first byte that wasn't on the
; screen already, we'll display the last page
CALL READ_LAST_PAGE
RNP_EXIT:
POP DX
POP CX
POP BX
POP AX
RET
READ_NEXT_PAGE ENDP


READ_PREV_PAGE PROC ; Read page before current page
PUSH AX
PUSH BX
PUSH CX
PUSH DX

; read enough immediately preceding the first byte not to
; be displayed to guarantee having a screen's worth

; first byte we don't want to display is first byte
; currently on screen
MOV DX,WORD PTR AFBOS
MOV CX,WORD PTR AFBOS+2
MOV WORD PTR AFBNOS ,DX
MOV WORD PTR AFBNOS+2,CX
; usually we position a full buffer in front of the first
; byte we don't want and read a full buffer
MOV BUFCNT,BUFSIZ
SUB DX,BUFSIZ
SBB CX,0
JAE RPP_POSITION ; see if too close to front
; but when we're too close to the beginning of the file we
; position to the beginning of the file and read
; however many bytes precede the one we don't want
MOV CX,WORD PTR AFBNOS
MOV BUFCNT,CX
MOV DX,0
MOV CX,0
RPP_POSITION:
MOV BX,LOGHNDL
MOV AH,42H ; position file read/write pointer
MOV AL,0 ; absolute position
CALL TRUEDOS
JNC RPP_POSITIONED
MOV AH,9
MOV DX,OFFSET EMEPFP
CALL TRUEDOS
STC
JMP RPP_EXIT
RPP_POSITIONED:
MOV AH,3FH ; read
MOV CX,BUFCNT
MOV DX,OFFSET BUF
CALL TRUEDOS
JNC RPP_BUFFER_READ
MOV AH,9
MOV DX,OFFSET EMERF
CALL TRUEDOS
STC
JMP RPP_EXIT
RPP_BUFFER_READ:
MOV BUFCNT,AX
; position within buffer to display last screen's worth
CALL FIND_LAST_PAGE
; if we have a full screen's worth, we're happy
CMP PAGEHGT,NLPS
JZ RPP_EXIT
; since there was less than a full screen's worth in front
; of the first byte we didn't want, we'll display the
; first page
CALL READ_FIRST_PAGE
RPP_EXIT:
POP DX
POP CX
POP BX
POP AX
RET
READ_PREV_PAGE ENDP

SCREEN_INIT PROC ; Screen services initialization
PUSH AX
PUSH CX
PUSH DI
PUSH ES
PUSH SI
; determine screen RAM segment
MOV SRSEG,0B000H ; assume MonoChrome
MOV AX,0
MOV ES,AX
MOV AL,ES:410H
AND AL,30H
CMP AL,30H
JZ SCREEN_INIT_KNOW_SEGMENT
MOV SRSEG,0B800H ; using Color/Graphics Monitor
SCREEN_INIT_KNOW_SEGMENT:
; save initial state of screen
MOV AX,SEG ORIG_SCREEN
MOV ES,AX
MOV DI,OFFSET ORIG_SCREEN
MOV CX,2000
MOV SI,0
PUSH DS
MOV DS,SRSEG
REP MOVSW
POP DS
MOV SROFF,0 ; start at beginning of screen
POP SI
POP ES
POP DI
POP CX
POP AX
RET
SCREEN_INIT ENDP


SCREEN_TERM PROC ; Screen services termination
PUSH AX
PUSH CX
PUSH DI
PUSH ES
PUSH SI
; restore original state of screen
MOV ES,SRSEG
MOV DI,0
MOV CX,2000
MOV SI,OFFSET ORIG_SCREEN
PUSH DS
MOV AX,SEG ORIG_SCREEN
MOV DS,AX
REP MOVSW
POP DS
POP SI
POP ES
POP DI
POP CX
POP AX
RET
SCREEN_TERM ENDP

CODE ENDS

END


  3 Responses to “Category : A Collection of Games for DOS and Windows
Archive   : EMPIREU.ZIP
Filename : CONSOLE.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/