⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xrect.asm

📁 视频游戏开发C语言源程序
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	mov  bx,di
	sar  di,2             ;X/4 = offset of first rectangle pixel in scan
	add  di,ax                    ;offset of first rectangle pixel in page
	add  di,[PageBase]            ;offset of first rectangle pixel in
                                      ; display memory
	and  bx,0003h                 ;look up left edge plane mask
	mov  ah,LeftClipPlaneMask[bx] ; to clip
	mov  bx,[EndX]
	and  bx,0003h                  ;look up right edge plane
	mov  al,RightClipPlaneMask[bx] ; mask to clip
	mov  bx,ax                     ;put the masks in BX

	mov  cx,[EndX]                 ;calculate # of addresses across rect
	mov  ax,[StartX]
	cmp  cx,ax
	jle  @@FillDone                ;skip if 0 or negative width
	dec  cx
	and  ax,not 011b
	sub  cx,ax
	sar  cx,2                 ;# of addresses across rectangle to fill - 1
	jnz  @@MasksSet           ;there's more than one pixel to draw
	and  bh,bl                ;there's only one pixel, so combine the left
                                  ; and right edge clip masks
@@MasksSet:
	mov  ax,[EndY]
	sub  ax,[StartY]          ;AX = height of rectangle
	jle  @@FillDone           ;skip if 0 or negative height
	mov  [Height],ax
	mov  ax,[_ScrnLogicalByteWidth]
	sub  ax,cx                ;distance from end of one scan line to start
	dec  ax                   ; of next
	mov  [NextScanOffset],ax
	mov  [RectAddrWidth],cx   ;remember width in addresses - 1
	mov  dx,SC_INDEX+1        ;point to Sequence Controller Data reg
                                  ; (SC Index still points to Map Mask)
@@FillRowsLoop:
	mov  cx,[RectAddrWidth]   ;width across - 1
	mov  al,es:[si]           ;read display memory to latch this scan
                                  ; line's pattern
	inc  si                   ;point to the next pattern scan line, wrapping
	jnz  short @@NoWrap       ; back to the start of the pattern if
	sub  si,4                 ; we've run off the end
@@NoWrap:
	mov  al,bh                ;put left-edge clip mask in AL
	out  dx,al                ;set the left-edge plane (clip) mask
        stosb                     ;draw the left edge (pixels come from latches;
                                  ; value written by CPU doesn't matter)
	dec  cx                   ;count off left edge address
	js   @@FillLoopBottom     ;that's the only address
	jz   @@DoRightEdge        ;there are only two addresses
	mov  al,00fh              ;middle addresses drawn 4 pixels at a pop
	out  dx,al                ;set middle pixel mask to no clip
	rep  stosb                ;draw middle addresses four pixels apiece
                                  ; (from latches; value written doesn't matter)
@@DoRightEdge:
	mov  al,bl                ;put right-edge clip mask in AL
	out  dx,al                ;set the right-edge plane (clip) mask
        stosb                     ;draw the right edge (from latches; value
                                  ; written doesn't matter)
@@FillLoopBottom:
	add  di,[NextScanOffset]  ;point to the start of the next scan
				  ; line of the rectangle
	dec  word ptr [Height]    ;count down scan lines
	jnz  @@FillRowsLoop
@@FillDone:
	mov  dx,GC_INDEX+1        ;restore the bit mask to its default,
	mov  al,0ffh              ; which selects all bits from the CPU
	out  dx,al                ; and none from the latches (the GC
				  ; Index still points to Bit Mask)

	pop  di                   ;restore caller's register variables
	pop  si
	mov  sp,bp                ;discard storage for local variables
	pop  bp                   ;restore caller's stack frame
        ret
_x_rect_pattern endp

;-----------------------------------------------------------------------
; Mode X (320x240, 256 colors) display memory to display memory copy
; routine. Left edge of source rectangle modulo 4 must equal left edge
; of destination rectangle modulo 4. Works on all VGAs. Uses approach
; of reading 4 pixels at a time from the source into the latches, then
; writing the latches to the destination. Copies up to but not
; including the column at SrcEndX and the row at SrcEndY. No
; clipping is performed. Results are not guaranteed if the source and
; destination overlap.
;
;
; Based on code originally published in DDJ Mag by M. Abrash
;
;C near-callable as:
;    void x_cp_vid_rect(int SrcStartX, int SrcStartY,
;       int SrcEndX, int SrcEndY, int DestStartX,
;       int DestStartY, unsigned int SrcPageBase,
;       unsigned int DestPageBase, int SrcBitmapWidth,
;       int DestBitmapWidth);

_x_cp_vid_rect proc
	ARG SrcStartX:word,SrcStartY:word,SrcEndX:word,SrcEndY:word,DestStartX:word,DestStartY:word,SrcPageBase:word,DestPageBase:word,SrcBitmapW:word,DestBitmapW:word
	LOCAL SrcNextOffs:word,DestNextOffs:word,RectAddrW:word,Height:word=LocalStk
	push    bp                  ;preserve caller's stack frame
	mov     bp,sp               ;point to local stack frame
	sub     sp,LocalStk         ;allocate space for local vars
	push    si                  ;preserve caller's register variables
	push    di
        push    ds

        cld
	mov     dx,GC_INDEX         ;set the bit mask to select all bits
	mov     ax,00000h+BIT_MASK  ; from the latches and none from
	out dx,ax                   ; the CPU, so that we can write the
				    ; latch contents directly to memory
	mov     ax,SCREEN_SEG       ;point ES to display memory
        mov     es,ax
	mov     ax,[DestBitmapW]
	shr     ax,2                ;convert to width in addresses
	mul     [DestStartY]        ;top dest rect scan line
	mov     di,[DestStartX]
	sar     di,2                ;X/4 = offset of first dest rect pixel in
				    ; scan line
	add     di,ax               ;offset of first dest rect pixel in page
	add     di,[DestPageBase]   ;offset of first dest rect pixel
				    ; in display memory
	mov     ax,[SrcBitmapW]
	sar     ax,2                ;convert to width in addresses
	mul     [SrcStartY]      ;top source rect scan line
	mov     si,[SrcStartX]
        mov     bx,si
	sar     si,2              ;X/4 = offset of first source rect pixel in
				  ; scan line
	add     si,ax             ;offset of first source rect pixel in page
	add     si,[SrcPageBase]  ;offset of first source rect
				  ; pixel in display memory
	and     bx,0003h                     ;look up left edge plane mask
	mov     ah,LeftClipPlaneMask[bx]  ; to clip
	mov     bx,[SrcEndX]
	and     bx,0003h                     ;look up right edge plane
	mov     al,RightClipPlaneMask[bx] ; mask to clip
	mov     bx,ax                        ;put the masks in BX

	mov     cx,[SrcEndX]              ;calculate # of addresses across
	mov     ax,[SrcStartX]            ; rect
        cmp     cx,ax
	jle     @@CopyDone                   ;skip if 0 or negative width
        dec     cx
        and     ax,not 011b
        sub     cx,ax
	sar     cx,2             ;# of addresses across rectangle to copy - 1
	jnz     @@MasksSet       ;there's more than one address to draw
	and     bh,bl            ;there's only one address, so combine the left
				 ; and right edge clip masks
@@MasksSet:
	mov     ax,[SrcEndY]
	sub     ax,[SrcStartY]     ;AX = height of rectangle
	jle     @@CopyDone         ;skip if 0 or negative height
	mov     [Height],ax
	mov     ax,[DestBitmapW]
	sar     ax,2               ;convert to width in addresses
	sub     ax,cx              ;distance from end of one dest scan line
	dec     ax                 ; to start of next
	mov     [DestNextOffs],ax
	mov     ax,[SrcBitmapW]
	sar     ax,2               ;convert to width in addresses
	sub     ax,cx              ;distance from end of one source scan line
	dec     ax                 ; to start of next
	mov     [SrcNextOffs],ax
	mov     [RectAddrW],cx     ;remember width in addresses - 1
	mov     dx,SC_INDEX+1      ;point to Sequence Controller Data reg
				   ; (SC Index still points to Map Mask)
	mov     ax,es              ;DS=ES=screen segment for MOVS
        mov     ds,ax
@@CopyRowsLoop:
	mov     cx,[RectAddrW]     ;width across - 1
	mov     al,bh              ;put left-edge clip mask in AL
	out     dx,al              ;set the left-edge plane (clip) mask
	movsb                      ;copy the left edge (pixels go through
				   ; latches)
	dec     cx                 ;count off left edge address
	js      @@CopyLoopBottom   ;that's the only address
	jz      @@DoRightEdge      ;there are only two addresses
	mov     al,00fh            ;middle addresses are drawn 4 pix per go
	out     dx,al              ;set the middle pixel mask to no clip
	rep     movsb              ;draw the middle addresses four pix per go
				   ; (pixels copied through latches)
@@DoRightEdge:
        mov     al,bl   ;put right-edge clip mask in AL
        out     dx,al   ;set the right-edge plane (clip) mask
        movsb           ;draw the right edge (pixels copied through
                        ; latches)
@@CopyLoopBottom:
	add     si,[SrcNextOffs]   ;point to the start of
	add     di,[DestNextOffs]  ; next source & dest lines
	dec     word ptr [Height]  ;count down scan lines
	jnz     @@CopyRowsLoop
@@CopyDone:
	mov     dx,GC_INDEX+1   ;restore the bit mask to its default,
        mov     al,0ffh         ; which selects all bits from the CPU
	out     dx,al           ; and none from the latches (the GC
                                ; Index still points to Bit Mask)
        pop     ds
	pop     di              ;restore caller's register variables
        pop     si
	mov     sp,bp           ;discard storage for local variables
	pop     bp              ;restore caller's stack frame
        ret
_x_cp_vid_rect  endp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Copy a rectangular region of a VGA screen, with x coordinates
; rounded to the nearest byte -- source and destination may overlap.
;
; C near-callable as:
;
; void x_shift_rect (WORD SrcLeft, WORD SrcTop,
;                    WORD SrcRight, WORD SrcBottom,
;                    WORD DestLeft, WORD DestTop, WORD ScreenOffs);
;
; SrcRight is rounded up, and the left edges are rounded down, to ensure
; that the pixels pointed to by the arguments are inside the rectangle.
;
; The width of the rectangle in bytes (width in pixels / 4)
; cannot exceed 255.
;
; ax, bx, cx, dx, and es eat hot lead.
;
; This function was written by Matthew MacKenzie
; matm@eng.umd.edu

	align   2
_x_shift_rect proc
ARG     SrcLeft,SrcTop,SrcRight,SrcBottom,DestLeft,DestTop,ScreenOffs:word
LOCAL   width_temp:word=LocalStk

	push bp
	mov bp, sp
	sub sp, LocalStk
	push si
	push di
	push ds

	; find values for width & x motion
	mov si, SrcLeft     ; source x in bytes
	sar si, 2

	mov di, DestLeft    ; destination x in bytes
	sar di, 2

	mov bx, SrcRight    ; right edge of source in bytes, rounded up
	add bx, 3
	sar bx, 2
	sub bx, si
	mov ax, bx          ; width - 1
	inc bx              ; we'll use this as an offset for moving up or down
	mov width_temp, bx

	cld                 ; by default, strings increment

	cmp si, di
	jge @@MovingLeft

; we're moving our rectangle right, so we copy it from right to left
	add si, ax          ; source & destination will start on the right edge
	add di, ax
	neg bx
	std                 ; strings decrement

@@MovingLeft:

; find values for height & y motion
	mov cx, _ScrnLogicalByteWidth ; bytes to move to advance one line
	mov ax, SrcTop
	mov dx, DestTop     ; default destination y
	cmp ax, dx
	jge @@MovingUp

; we're moving our rectangle down, so we copy it from bottom to top
	mov ax, SrcBottom   ; source starts at bottom
	add dx, ax          ; add (height - 1) to destination y
	sub dx, SrcTop
	neg cx              ; advance up screen rather than down

@@MovingUp:
	push dx             ; save destination y during multiply
	mul _ScrnLogicalByteWidth
	add si, ax          ; add y in bytes to source
	pop ax              ; restore destination y
	mul _ScrnLogicalByteWidth
	add di, ax          ; add y in bytes to destination

	sub cx, bx          ; final value for moving up or down

	add si, ScreenOffs  ; source & destination are on the same screen
	add di, ScreenOffs

	mov dx, SC_INDEX    ; set map mask to all four planes
	mov ax, 00f02h
	out dx, ax

	mov dx, GC_INDEX    ; set bit mask to take data from latches
	mov ax, BIT_MASK    ;  rather than CPU
	out dx, ax

	mov ax, SCREEN_SEG  ; source and destination are VGA memory
	mov es, ax
	mov ds, ax

	mov ah, byte ptr width_temp ; width in bytes should fit in 8 bits

	mov bx, SrcBottom   ; height - 1
	sub bx, SrcTop

	mov dx, cx          ; bytes to add to advance one line

	xor ch, ch          ; ready to rock

@@LineLoop:
	mov cl, ah          ; load width in bytes
	rep movsb           ; move 4 pixels at a time using latches (YOW!)

	add si, dx          ; advance source by one line
	add di, dx          ; advance destination by one line

	dec bx              ; line counter
	jge @@LineLoop      ; 0 still means one more to go

	mov dx, GC_INDEX + 1; set bit mask to take data from CPU (normal setting)
	mov al, 0ffh
	out dx, al

; kick
	pop ds
	pop di
	pop si
	mov sp, bp
	pop bp

	ret
_x_shift_rect endp

	end

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -