home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C!T ROM 2
/
ctrom_ii_b.zip
/
ctrom_ii_b
/
PROGRAM
/
ASSEMBLE
/
80X0992
/
DRAWIMAG.ASM
< prev
next >
Wrap
Assembly Source File
|
1992-07-30
|
14KB
|
377 lines
;
; DRAWIMAG.ASM
;
; Author: Matt Pritchard
; released to the public domain
;
VGA_SEGMENT EQU 0A000H ;Vga Memory Segment
SCREEN_XWIDTH EQU 360 ;Screen width in Pixels
SCREEN_WIDTH EQU 90 ;Screen width in bytes
GC_INDEX EQU 03CEH ;VGA Graphics Controller
SC_INDEX EQU 03C4H ;VGA Sequence controller
CRTC_INDEX EQU 03D4H ;VGA CRT Controller
MISC_OUTPUT EQU 03C2H ;VGA Misc Register
MAP_MASK EQU 02 ;Map Register #
READ_MAP EQU 04 ;Read Map Register #
;DRAWIMAGE (IconImageSeg%, IconImageOfs%, Xpos%, Ypos%, Width%, Hieght%)
;
; % = 16 bit integer value passed BY VALUE on stack.
;
;Draws a variable sized Image, only the non zero pixels.
;The width of the image must be a multiple of 4.
;
;Preserves: DS, SI, DI, BP
;Sets: Dir flag - Clear
;Destroys: AX, BX, CX, DX, ES, Flags
DI_STACK STRUC
DI_Jump DW ? ;Jump Table offset
DI_Repeat DB ?,? ;# of 16 byte repeat copies
DI_NextL DW ? ;Offset to next line start
DI_Addr DW ? ;Saved Image Address
DW ? ;Saved DI
DW ? ;Saved SI
DW ? ;Saved DS
DW ? ;Saved BP
DD ? ;Save Caller Addr
DI_YSIZE DW ? ;Height of Image
DI_XSIZE DW ? ;Width of Image (mult of 4)
DI_YPOS DW ? ;Y pos of Image (Upper left)
DI_XPOS DW ? ;X pos of Image (Upper left)
DI_IOFF DW ? ;Offset of image data
DI_ISEG DW ? ;Segment of image data DI_STACK
ENDS
PUBLIC DRAWIMAGE
.CODE
;Table for Inline (Unrolled loop) entry
JumpTable DW @Copy0, @Copy1, @Copy2, @Copy3
DW @Copy4, @Copy5, @Copy6, @Copy7
DW @Copy8, @Copy9, @Copy10, @Copy11
DW @Copy12, @Copy13, @Copy14, @Copy15
DRAWIMAGE PROC FAR
PUSH BP ;Save Bp
PUSH DS ;Save Data Seg
PUSH SI ;
PUSH DI ;
SUB SP, 8 ;Alloc Temp Stack Variables
MOV BP, SP ;Set to address of bp
MOV AX, VGA_SEGMENT ;VGA Graphics Segment
MOV ES, AX ;ES for Vga pixel access
;Setup all our stack variables
MOV BX, [BP].DI_XSIZE ;Get image width
SHR BX, 1 ;Get width /2
MOV SI, BX ;Put (Width/4)*2 in SI
SHR BX, 1 ;Get Width /4
MOV [BP].DI_XSIZE, BX ;Save width/4 as width
MOV DX, SCREEN_WIDTH ;Get Screen width (bytes)
SUB DX, AX ;Get Dist to start of next line
MOV [BP].DI_NextL, DX ;Save info for later
AND SI, 000Fh ;Get (width/4) mod 16
MOV AX, CS:JumpTable[SI] ;Get 1st pass jump addr
MOV [BP].DI_Jump, AX ;Save for reference...
MOV CL, 4 ;4 shifts = /16
SHR BX, CL ;Get (Width/4) / 16
INC BL ;Add 1 for 0 fall through
MOV [BP].DI_Repeat, BL ;Save Repeat block count
;Compute address of Image on Screen
MOV AX, SCREEN_WIDTH ;Get Screen width (bytes)
MUL [BP].DI_YPOS ;AX = Ypos * Screen Width
MOV DI, [BP].DI_XPOS ;Get Xpos
MOV CX, DI ;Copy of Xpos in CX
SHR DI, 1 ;XByte = Xpos/4
SHR DI, 1
ADD DI, AX ;Addr = Xpos/4 + Ypos*Screen Width
MOV [BP].DI_Addr,DI ;Save Screen starting Write Addr
MOV AX, 1102h ;Plane Mask & Plane Select
AND CL, 3 ;Get Plane # in CL (Xpos AND 3)
SHL AH, CL ;Set Mask to correct plane
MOV DX, SC_INDEX ;Setup to select plane
OUT DX, AX ;Select Plane...
INC DX ;Future OUTs will be plane select
MOV DS, [BP].DI_ISEG ;Get Image SEGMENT in DS
MOV CH,04h ;4 Planes to Draw
CLD ;String copy opcodes forward
;Copy a plane (1/4) of the image data
@DI_Copy_Plane:
MOV SI,[BP].DI_IOFS ;Get image start addr in (DS:)SI
MOV DI,[BP].DI_Addr ;Get Image write addr in (ES:)DI
MOV CL,[BP].DI_Repeat ;Get block repeat count
MOV DX,[BP].DI_YSIZE ;Get # of lines to copy
MOV BX,[BP].DI_Jump ;Get starting addr
JMP NEAR [BX] ;skip to correct starting point
;Copy a block of 16 pixels
;Loop unrolled to x16 for maximum performance
@DI_Copy_Loop:
MOV AL,[SI] ;Read Byte #1
OR AL,AL ;Byte = 0?
JZ @ND1 ;If so, Don't Draw
MOV ES:[DI],AL ;Draw byte #1
@ND1:
INC DI ;Advance Dest Addr
ADD SI,4 ;Skip to Next Byte in same plane
@Copy15:
MOV AL,[SI] ;Read Byte #2
OR AL,AL ;Byte =0?
JZ @ND2 ;If so, Don't Draw
MOV ES:[DI],AL ;Draw byte #2
@ND2:
INC DI ;Advance Dest Addr
ADD SI,4 ;Skip to Next Byte in same plane
@Copy14:
MOV AL,[SI] ;Read Byte #3
OR AL,AL ;Byte =0?
JZ @ND3 ;If so, Don't Draw
MOV ES:[DI],AL ;Draw byte #3
@ND3:
INC DI ;Advance Dest Addr
ADD SI,4 ;Skip to Next Byte in same plane
@Copy13:
MOV AL,[SI] ;Read Byte #4
OR AL,AL ;Byte =0?
JZ @ND4 ;If so, Don't Draw
MOV ES:[DI],AL ;Draw byte #4
@ND4:
INC DI ;Advance Dest Addr
ADD SI,4 ;Skip to Next Byte in same plane
@Copy12:
MOV AL,[SI] ;Read Byte #5
OR AL,AL ;Byte =0?
JZ @ND5 ;If so, Don't Draw
MOV ES:[DI],AL ;Draw byte #5
@ND5:
INC DI ;Advance Dest Addr
ADD SI,4 ;Skip to Next Byte in same plane
@Copy11:
MOV AL,[SI] ;Read Byte #6
OR AL,AL ;Byte =0?
JZ @ND6 ;If so, Don't Draw
MOV ES:[DI],AL ;Draw byte #6
@ND6:
INC DI ;Advance Dest Addr
ADD SI,4 ;Skip to Next Byte in same plane
@Copy10:
MOV AL,[SI] ;Read Byte #7
OR AL,AL ;Byte =0?
JZ @ND7 ;If so, Don't Draw
MOV ES:[DI],AL ;Draw byte #7
@ND7:
INC DI ;Advance Dest Addr
ADD SI,4 ;Skip to Next Byte in same plane
@Copy9:
MOV AL,[SI] ;Read Byte #8
OR AL,AL ;Byte =0?
JZ @ND8 ;If so, Don't Draw
MOV ES:[DI],AL ;Draw byte #8
@ND8:
INC DI ;Advance Dest Addr
ADD SI,4 ;Skip to Next Byte in same plane
@Copy8:
MOV AL,[SI] ;Read Byte #9
OR AL,AL ;Byte =0?
JZ @ND9 ;If so, Don't Draw
MOV ES:[DI],AL ;Draw byte #9
@ND9:
INC DI ;Advance Dest Addr
ADD SI,4 ;Skip to Next Byte in same plane
@Copy7:
MOV AL,[SI] ;Read Byte #10
OR AL,AL ;Byte =0?
JZ @ND10 ;If so, Don't Draw
MOV ES:[DI],AL ;Draw byte #10
;Routine: CLEAR_VGA_SCREEN (*Color%)
; Sets the Entire Screen to one Color
;
;BASIC: DECLARE SUB CLEAR.VGA ALIAS "CLEAR_VGA_SCREEN"
;(BYVAL ColorNum%)
;
;C: pascal void CLEAR_VGA_SCREEN ( int ColorNum );
CVS_STACK STRUC
DW ? ;saved DI
DW ? ;saved BP
DD ? ;Caller
CVS_COLOR DB ?,? ;Color to Fill With CVS_STACK ENDS
PUBLIC CLEAR_VGA_SCREEN
CLEAR_VGA_SCREEN PROC FAR
PUSH BP ; Save registers
PUSH DI
MOV BP,SP ; Setup Stack frame
MOV DX, SC_INDEX ; Select All Panes
MOV AX, 0F02H ; Map Mask (02) = 0F
OUT DX, AX
MOV AX, VGA_SEGMENT ; Point to VGA memory
MOV ES, AX
MOV DI, 0
MOV AL,[BP].CVS_COLOR ; Get Color to set
MOV AH,AL ; Copy for Word Write
MOV CX, 10800 ; # of bytes in 360x240 mode
REP STOSW ; Blast it!
POP DI ; restore registers
POP BP
RET 2 ; exit & clean up stack
CLEAR_VGA_SCREEN ENDP
;Routine: SETPOINT (*Xpos1, *Ypos1%, *ColorNum%)
; Sets a single pixel in 360x240 256 color mode
;
;BASIC: DECLARE SUB SETPOINT (BYVAL X%, BYVAL Y%, BYVAL ColorNum%)
;C: pascal void SETPOINT (int Xpos, int Ypos, int ColorNum);
SP_STACK STRUC
DW ? ;saved BP
DD ? ;Caller
SETP_COLOR DB ?,? ;Pixel color
SETP_YPOS DW ? ;Pixel Y pos
SETP_XPOS DW ? ;Pixel X pos SP_STACK ENDS
PUBLIC SETPOINT
SETPOINT PROC FAR
PUSH BP ;Save base pointer
MOV BP,SP ;Set up stack frame
MOV AX, SCREEN_WIDTH ;Get Screen Line Width
MUL [BP].SETP_YPOS ;AX = Ypos * 90
MOV BX,[BP].SETP_XPOS ;Get Xpos
MOV CX, BX ;Save copy of Xpos
SHR BX, 1 ;XByte = Xpos/4
SHR BX, 1
ADD BX,AX ;BX = 90 * Ypos + Xpos/4
MOV AX, 0102h ;Plane Mask & Select Register
AND CL, 3 ;Get plane # from Xpos
SHL AH, CL ;Shift to Get Plane Value
MOV DX, SC_INDEX ;Setup to select plane
OUT DX, AX ;Select Plane...
MOV AX,VGA_SEGMENT ;Setup Vga Segment
MOV ES,AX
MOV AL,[BP].SETP_COLOR ;Get Color
MOV ES:[BX], AL ;Draw Point
POP BP ;Restore Bp
RET 6 ;Exit and Clean up Stack
SETPOINT ENDP
;Routine: int READPOINT (*Xpos, *Ypos%)
; Returns the color of single pixel in AX
;
;BASIC: DECLARE FUNCTION READPOINT% (BYVAL X%, BYVAL Y%)
;C: pascal int READPOINT( int Xpos, int Ypos );
RP_STACK STRUC
DW ? ;saved Bp
DD ? ;Caller
RP_YPOS DW ? ;Pixel Y pos
RP_XPOS DW ? ;Pixel X pos RP_STACK ENDS
PUBLIC READPOINT
READPOINT PROC FAR
PUSH BP
MOV BP,SP ;Set up stack frame
MOV AX, SCREEN_WIDTH ;Get Screen Line Width
MUL [BP].RP_YPOS ;AX = Ypos * Screen Width
MOV BX,[BP].RP_XPOS ;Get Xpos
MOV CX, BX ;Save Copy of Xpos
SHR BX, 1 ;XByte = Xpos/4
SHR BX, 1
ADD BX,AX ;BX = Screen_Width * Ypos + Xpos/4
MOV AL, READ_MAP ;GC Read Mask Register
MOV AH, CL ;Get Xpos
AND AH, 3 ;& mask out Plane #
MOV DX, GC_INDEX ;Setup to select Read Mask
OUT DX, AX ;Select Plane...
MOV AX,VGA_SEGMENT ;Setup Vga Segment
MOV ES,AX
XOR AX,AX ;Clear Return Value
MOV AL,ES:[BX] ;Get Color of Pixel
POP BP ;Restore registers
RET 4 ;Exit and Clean up Stack
READPOINT ENDP
; EOF DRAWIMAG.ASM