Category : C Source Code
Archive   : IMDSRC78.ZIP
Filename : DISPSUB.ASM

 
Output of file : DISPSUB.ASM contained in archive : IMDSRC78.ZIP
TITLE dispsub

; Assembly language subroutines for DISPDRIV module.


ifdef _286
.286
endif


DISPSUB_TEXT SEGMENT BYTE PUBLIC 'CODE'
DISPSUB_TEXT ENDS
DISPSUB_DATA SEGMENT WORD PUBLIC 'DATA'
DISPSUB_DATA ENDS
CONST SEGMENT WORD PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT WORD PUBLIC 'BSS'
_BSS ENDS
DGROUP GROUP CONST, _BSS, DISPSUB_DATA
ASSUME CS: DISPSUB_TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
DISPSUB_DATA SEGMENT
DISPSUB_DATA ENDS

DISPSUB_TEXT SEGMENT

; EgaRegs is the address of what would be the beginning of a complete set
; of register tables. Since we are only using one particular mode, we don't
; allocate the entire set, but adjust EgaRegs backwards by the appropriate
; amount. (Note that the offset of EgaRegs may actually be a negative
; number. This does not cause any problem.)

EgaRegs equ $-(40h*18)

; Columns, rows, pixels, page size
db 80, 36, 14
dw 0B400h

; Sequencer registers
db 01h, 0Fh, 00h, 06h

; Miscellaneous output register
db 0ABh

; CRTC parameters
db 64h, 4Fh, 53h, 21h, 53h, 00h, 0F0h, 1Fh, 8 dup (00h)
db 0E0h, 2Ch, 0DFh, 28h, 0Fh, 0E1h, 0Ch, 0E3h, 0FFh

; Attribute registers
db 00h, 01h, 02h, 03h, 04h, 05h, 14h, 07h
db 38h, 39h, 3Ah, 3Bh, 3Ch, 3Dh, 3Eh, 3Fh
db 01h, 00h, 0Fh, 00h

; Graphics controller registers
db 00h, 00h, 00h, 00h, 00h, 00h, 05h, 0Fh, 0FFh

PUBLIC _putmem
_putmem PROC FAR
push bp
mov bp,sp

; segment = 4
; offset = 6
; value = 8

mov es, [bp+6] ;segment
mov bx,[bp+8] ;offset
mov ax,[bp+10] ;value
mov es:[bx],al

mov sp,bp
pop bp
ret

_putmem ENDP



PUBLIC _getmem
_getmem PROC FAR
push bp
mov bp,sp


; segment = 4
; offset = 6

mov es, [bp+6] ;segment
mov bx,[bp+8] ;offset
mov al,es:[bx]
sub ah,ah

mov sp,bp
pop bp
ret

_getmem ENDP


; int WritePixelEGA (line, samp, DN);
;
; WritePixelEGA displays a pixel on the EGA screen at the desired location.
;
; Parameters:
; line the line to display the pixel at (starts at 1)
; samp the sample to display the pixel at (starts at 1)
; DN the DN to write
;
; Registers:
; DI pointer to video memory (ES segment used)
; BL bit mask used to load pixels to bitplanes
;
; line = BP+6
; sample = BP+8
; DN = BP+10

PUBLIC _WritePixelEGA
_WritePixelEGA PROC FAR

PUSH BP
MOV BP, SP
PUSH DI

; Calculate the starting address in memory
; address := 80*(line-1) + (samp-1) shr 3;
MOV AX, [BP+6] ; get line parameter
DEC AX ; convert to start at 0 system
JL CLIP ; Abort if out of range
CMP AX, 479 ; EGA480
JG CLIP
MOV DI, AX
SHL DI, 1 ; multiply by 80
SHL DI, 1
ADD DI, AX
SHL DI, 1
SHL DI, 1
SHL DI, 1
SHL DI, 1
MOV AX, [BP+8] ; get samp parameter
DEC AX ; convert to start at 0 system
JL CLIP ; Abort if out of range
CMP AX, 639
JG CLIP
SHR AX, 1 ; divide it by 8
SHR AX, 1
SHR AX, 1
ADD DI, AX ; calculate the final memory offset
; and put in the video pointer

; Select Write Mode 2
MOV DX, 3CEH
MOV AL, 5
OUT DX, AL
MOV DX, 3CFH
MOV AL, 2
OUT DX, AL


MOV AX, 0A000H ; ES = EGA buffer segment address
MOV ES, AX

; Initialize bit mask
; mask = 0x80 >> ((samp-1) & 7);
MOV CX, [BP+8] ; get samp parameter
DEC CX
AND CX, 7
MOV BL, 80H ; shift bit over to start at the
SHR BL, CL ; right pixel

MOV DX, 3CEH
MOV AL, 8 ; Load the bit mask
OUT DX, AL
MOV DX, 3CFH
MOV AL, BL
OUT DX, AL

MOV AL, ES:[DI] ; Latch the bytes from each bitplane
MOV AX, [BP+10] ; Get the pixel value
MOV ES:[DI], AL ; Write the bytes back to the bitplanes



; Restore Write Mode 0
MOV DX, 3CEH
MOV AL, 5
OUT DX, AL
MOV DX, 3CFH
MOV AL, 0
OUT DX, AL

; Restore default bit mask
MOV DX, 3CEH
MOV AL, 8
OUT DX, AL
MOV DX, 3CFH
MOV AL, 0FFH
OUT DX, AL


CLIP:
POP DI
MOV SP,BP
POP BP
RET

_WritePixelEGA ENDP


; int DisplayLineEGA (buffer, line, samp, ns);
;
; DisplayLineEGA displays a line of pixels in a buffer on the EGA screen
; at the desired location.
;
; Parameters:
; buffer the buffer of bytes containing the pixels (nibbles) to
; be displayed
; line the line to display the pixels at (starts at 1)
; samp the sample to display the first pixel at (starts at 1)
; ns the number of samples to display
;
; Registers:
; DI pointer to video memory (ES segment used)
; SI pointer to pixel buffer (DS segment used)
; BL bit mask used to load pixels to bitplanes
; CX sample counter
;
; buffer = 6
; line = 8
; samp = 10
; ns = 12

PUBLIC _DisplayLineEGA
_DisplayLineEGA PROC FAR

PUSH BP
MOV BP, SP
PUSH DS
PUSH DI
PUSH SI

MOV AX, [BP+6] ; get segment of buffer
MOV DS, AX
MOV SI, [BP+8] ; get offset of buffer

; Calculate the starting address in memory
; address := 80*(line-1) + (samp-1) shr 3;
MOV AX, [BP+10] ; get line parameter
DEC AX ; convert to start at 0 system
MOV DX, 80 ; multiplying line by 80
MUL DX ;
MOV DX, [BP+12] ; get samp parameter
DEC DX ; convert to start at 0 system
SHR DX, 1 ; divide it by 8
SHR DX, 1
SHR DX, 1
ADD AX, DX ; calculate the final memory offset
MOV DI, AX ; and put in the video pointer

MOV AX, 0A000H ; ES = EGA buffer segment address
MOV ES, AX

; Select Write Mode 2
MOV DX, 3CEH
MOV AL, 5
OUT DX, AL
MOV DX, 3CFH
MOV AL, 2
OUT DX, AL

; Initialize bit mask
; mask := $80 shr ((samp-1) and 7);
MOV CX, [BP+12] ; get samp parameter
DEC CX
AND CX, 7
MOV BL, 80H ; shift bit over to start at the
SHR BL, CL ; right pixel


MOV CX, [BP+14] ; Start loop counter with ns parameter
MOV DX, 3CEH ; point DX to the right port

SAMPLOOP:
MOV AL, 8 ; Load the bit mask
OUT DX, AL
INC DX
MOV AL, BL
OUT DX, AL
DEC DX

MOV AL, ES:[DI] ; Latch the bytes from each bitplane
MOV AL, [SI] ; Get the nibble from the linebuf
MOV ES:[DI], AL ; Write the bytes back to the bitplanes

SHR BL, 1 ; shift the bit over in the bit mask
JNC ENDLOOP
; if the bit fell out the other end
MOV BL, 80H ; then move to the next byte in
INC DI ; video memory

ENDLOOP:
INC SI ; point to the next pixel
LOOP SAMPLOOP ; loop until all pixels are done


; Restore Write Mode 0
MOV DX, 3CEH
MOV AL, 5
OUT DX, AL
MOV DX, 3CFH
MOV AL, 0
OUT DX, AL

; Restore default bit mask
MOV DX, 3CEH
MOV AL, 8
OUT DX, AL
MOV DX, 3CFH
MOV AL, 0FFH
OUT DX, AL


POP SI
POP DI
POP DS
MOV SP,BP
POP BP
RET

_DisplayLineEGA ENDP







; int ClearDisplayEGA (DN,dispnl);
;
; ClearDisplayEGA sets the whole EGA screen to the DN pixel value
;
; Parameters:
; DN the pixel value to set the screen to
;
; Registers:
; DI pointer to video memory (ES segment used)
;
;
; DN = 6

PUBLIC _ClearDisplayEGA
_ClearDisplayEGA PROC FAR

PUSH BP
MOV BP, SP
PUSH DI

MOV AX, 0A000H ; ES = EGA buffer segment address
MOV ES, AX

; Select Write Mode 2
MOV DX, 3CEH
MOV AL, 5
OUT DX, AL
MOV DX, 3CFH
MOV AL, 2
OUT DX, AL

; Set bit mask to all bits on
MOV DX, 3CEH
MOV AL, 8
OUT DX, AL
MOV DX, 3CFH
MOV AL, 0FFH
OUT DX, AL

MOV AL, [BP+6] ; Get the pixel value
MOV DI, 0 ; Start at beginning of video memory
mov si, [BP+8]
cmp si,350 ; check for 350 or 480 line display
jne BYTE480
BYTELOOP:
MOV BL, ES:[DI] ; Latch the bytes from each bitplane
MOV ES:[DI], AL ; Write the bytes back to the bitplanes
INC DI ; point to the next byte
CMP DI, 28000 ; how many lines to clear
JNZ BYTELOOP ; loop until whole screen cleared
jmp RESTORE

BYTE480:
MOV BL, ES:[DI] ; Latch the bytes from each bitplane
MOV ES:[DI], AL ; Write the bytes back to the bitplanes
INC DI ; point to the next byte
CMP DI, 38400 ; how many lines to clear
JNZ BYTE480 ; loop until whole screen cleared

RESTORE:
; Restore Write Mode 0
MOV DX, 3CEH
MOV AL, 5
OUT DX, AL
MOV DX, 3CFH
MOV AL, 0
OUT DX, AL

POP DI
MOV SP,BP
POP BP
RET

_ClearDisplayEGA ENDP





PUBLIC _PGAsend
_PGAsend PROC FAR
; command = 6
; len = 8

PUSH BP
MOV BP, SP
PUSH SI

MOV AX, 0C600H

MOV ES, AX
MOV CX, [BP+8] ; put len in CX
MOV SI, [BP+6] ; get command array address in SI
WAIT1:
MOV BL, ES:[0300H] ; OutWritePtr
MOV AL, ES:[0301H] ; OutReadPtr
SUB AL, BL
DEC AL ; calculate numbytes
CMP AL, CL ; and compare it with len
JB WAIT1 ; wait until there's room in buffer
SUB BH, BH
OUTLOOP:
MOV AL, [SI] ; get the command byte
MOV ES:[BX], AL ; send it to the PGA
INC SI ; point to next command byte
INC BL ; increment the OutWritePtr
LOOP OUTLOOP ; loop until done all bytes

MOV ES:[0300H], BL ; save the OutWritePtr

POP SI
MOV SP, BP
POP BP
RET
_PGAsend ENDP

; Set640x480 puts an EGA card with a 24mhz feature adapter into 640x480
; graphics mode. Once the card in in the mode, pixels may be written using
; conventional EGA programming techniques. The only difference is there are
; more scan lines. (And there is only a single display page, not two.)

; The 24mhz feature adapter was described in the September 16, 1986 PC
; Magazine, page 298.

SaveTable equ 04A8h
SaveTableLen equ 7 ; Number of DWORDs in SaveTable

PUBLIC _EGAinit
_EGAinit PROC FAR

push ds
push es
push ax
push bx
push cx

xor ax, ax
mov es, ax

lds bx, es:SaveTable ; Get old save table

push ds ; Stash away for when we return
push bx

mov cx, SaveTableLen*2
add bx, SaveTableLen*4
SavePush: ; Make a copy of save table on stack
dec bx
dec bx
push [bx]
loop SavePush
mov bx, sp

mov ss:[bx], offset EgaRegs ; Point to our register set
mov ss:[bx+2], cs

CLI
mov es:SaveTable, bx ; Make our copy the active one
mov es:SaveTable+2, ss
STI

mov ax,0010h ; Set 640x480 color graphics
int 10h

CLI
add sp, SaveTableLen*4 ; Deallocate our copy from stack
pop es:SaveTable
pop es:SaveTable+2 ; Restore original save table
STI

pop cx
pop bx
pop ax
pop es
pop ds

ret

_EGAinit ENDP


DISPSUB_TEXT ENDS
END


  3 Responses to “Category : C Source Code
Archive   : IMDSRC78.ZIP
Filename : DISPSUB.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/