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

📄 xmain.asm

📁 视频游戏开发源码
💻 ASM
📖 第 1 页 / 共 4 页
字号:
	mov  [_SplitScrnActive],TRUE
	mov  ax,[Line]
	jns  @@NotNeg    ; Check that Split Scrn start scan line is +ve

	mov  ax,0        ; Since -ve set to 0

@@NotNeg:
	mov  [_SplitScrnScanLine],ax   ; save the scanline



	or    [DoubleScanFlag],0
	jz    @@NotDoubleScanned
	shl   ax,1
	dec   ax
@@NotDoubleScanned:
	;mov  cl,[DoubleScanFlag]
	;shl  ax,cl            ; Mode X 200 and 240 line modes are actually
				  ; 400 and 480 lines that are double scanned
				  ; so for start scanline multiply required ModeX
				  ; scan line by 2 if its a double scanned mode


	mov  bx,ax            ; save the scanline


	WaitVsyncStart        ; wait for vertical retrace

	cli                   ; Dont allow register setting to be interrupted
	mov  dx,CRTC_INDEX
	mov  ah,bl
	mov  al,LINE_COMPARE
	out  dx,ax            ; Bits 7-0 of the split screen scan line

	mov  ah,bh
	and  ah,1
	shl  ah,4
	mov  al,OVERFLOW     ; Bit 4 of overflow register = Bit 8 of split
	out  dx,al           ; screen scan line,
	inc  dx              ; So using readability of VGA registers
	in   al,dx           ; Read the OVERFLOW register, and set the
	and  al, not 10h     ; bit corresponding to Bit 8 (above)
	or   al,ah
	out  dx,al

	dec  dx
	mov  ah,bh
	and  ah,2
	ror  ah,3
	mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =
	out  dx,al             ; Bit 9 of split screen scan line
	inc  dx                ; As we did before, update the apropriate
	in   al,dx             ; bit without disturbing the rest
	and  al, not 40h
	or   al,ah
	out  dx,al
	sti                    ; Registers are set, so interrupts are safe

	mov  ax,[_ScrnPhysicalHeight]     ; Determine where the first byte
	sub  ax,[_SplitScrnScanLine]      ; of the non split screen video ram
	mov  [_SplitScrnVisibleHeight],ax ; starts and store it for reference

	mov  bx,[_ScrnLogicalByteWidth]
	mul  bx
	mov  [_Page0_Offs],ax
	mov  [_Page1_Offs],ax
	mov  [_Page2_Offs],ax

	; calculate no. non split screen rows in video ram
	mov  cx,0ffffh             ; cx = Maximum video ram offset
	sub  cx,ax                 ; cx = cx - _Page0_Offs
	xchg cx,ax                 ; swap cx and ax
	sub  dx,dx                 ; DX:AX is divide operand,  set DX = 0
	div  bx                    ; divide ax (prev cx) by
				   ; ScrnLogicalByteWidth

	mov  [_ScrnLogicalHeight],ax     ; Save Screen Logical Height
	cmp   ax,[_BottomClip]
	jle   @@BottomClipOK             ; Adjust Clip Rectangle if necessary
	mov   [_BottomClip],ax
@@BottomClipOK:
	sub  ax,[_SplitScrnScanLine]     ; Update the maximum Y position of
	mov  [_MaxScrollY],ax            ; Physical screen in logical screen

	xchg cx,ax                       ; restore original ax (MainScrnOfs)
	mov  bh,al                       ; Set the visible screen start address
	mov  ch,ah                       ; to the top left corner of the virtual
	jmp  StartAddrEntry              ; screen
_x_set_splitscreen      endp


;-----------------------------------------------------------------------
; Mode X (256 color mode) Page flip primer
; No clipping is performed.
; C near-callable as:
;
;    void x_page_flip(unsigned int x, unsigned int y);
;
; Swaps visible and hidden page offsets and then executes the SetStartAddr
; to achieve a page flip.
;
; SEE x_set_start_addr below
;
; Written by Themie Gouthas
;------------------------------------------------------------------------

_x_page_flip proc
	ARG x:word,y:word
	push  bp                  ;preserve caller's stack frame
	mov   bp,sp               ;point to local stack frame
	push  si

	mov  si,[x]
	mov  ax,[_ScrnLogicalByteWidth]     ; Calculate Offset increment
	mov  cx,[y]
	mul  cx                             ; for Y
	cmp  [_DoubleBufferActive],TRUE     ; Do we have double buffering ?
	je   @@DoubleBuffer
	cmp  [_TrippleBufferActive],TRUE
	jne   PageFlipEntry1

; TrippleBuffer
	mov  bx,[_HiddenPageOffs]
	xchg bx,[_VisiblePageOffs]
	xchg bx,[_WaitingPageOffs]
	mov  [_HiddenPageOffs],bx
	mov  bx,[_VisiblePageIdx]
	inc  bx
	cmp  bx,3
	jne  @@IdxOk
	xor  bx,bx
@@IdxOk:
	mov  [_VisiblePageIdx],bx
	jmp  short PageFlipEntry2
@@DoubleBuffer:
	mov  bx,[_HiddenPageOffs]
	xchg bx,[_VisiblePageOffs]          ; Swap the Page Offsete
	xchg [_HiddenPageOffs],bx
	xor  [_VisiblePageIdx],01h          ; Set the Visible page index
	jmp  short PageFlipEntry2
_x_page_flip endp


;-----------------------------------------------------------------------
; Mode X (256 color mode) Set Mode X non split screen start address
;   of logical screen.
; C near-callable as:
;
;    void x_set_start_addr(unsigned int x, unsigned int y);
;
; Params: StartOffset is offset of first byte of logical screen ram
;           (Useful if you want to double buffer by splitting your non
;            split screen video ram into 2 pages)
;        X,Y coordinates of the top left hand corner of the physical screen
;           within the logical screen
;           X must not exceed (Logical screen width - Physical screen width)
;           Y must not exceed (Logical screen height - Physical screen height)
;
;
; Written by Themie Gouthas,
; Parts addapted from M. Abrash code published in DDJ Mag.
;------------------------------------------------------------------------
_x_set_start_addr proc
	ARG x:word,y:word
	push bp
	mov  bp,sp
	push si

	mov  si,[x]
	mov  ax,[_ScrnLogicalByteWidth]     ; Calculate Offset increment
	mov  cx,[y]                         ; for Y
	mul  cx
	cmp  [_DoubleBufferActive],TRUE     ; Do we have double buffering ?
	je   @@PageResolution
	cmp  [_TrippleBufferActive],TRUE
	je   @@PageResolution
PageFlipEntry1:
	add  ax,[_Page0_Offs]               ; no - add page 0 offset
	jmp  short @@AddColumn

PageFlipEntry2:

	mov  [_PhysicalStartPixelX],si
	mov  [_PhysicalStartY],cx

@@PageResolution:
	add  ax,[_VisiblePageOffs]          ; Add visible page offset

@@AddColumn:
	mov  cx,si
	shr  cx,2
	mov  [_PhysicalStartByteX],cx
	add  ax,cx                          ; add the column offset for X
	mov  bh,al                          ; setup CRTC start addr regs and
						; values in word registers for
	mov  ch,ah                          ; fast word outs

StartAddrEntry:
	mov  bl,ADDR_LOW
	mov  cl,ADDR_HIGH
	and  si,0003h             ; select pel pan register value for the
	mov  ah,PelPanMask[si]    ; required x coordinate
	mov  al,PEL_PANNING+20h
	mov  si,ax

	cmp  [_VsyncHandlerActive],TRUE
	jne   @@NoVsyncHandler
; NEW STUFF
@@WaitLast:
	cmp   [_StartAddressFlag],0
	jne   @@WaitLast
	cli
	mov  [_WaitingStartLow],bx
	mov  [_WaitingStartHigh],cx
	mov  [_WaitingPelPan],si
	mov  [_StartAddressFlag],1
	sti
	jmp  short @@Return

@@NoVsyncHandler:
	mov  dx,INPUT_STATUS_0    ;Wait for trailing edge of Vsync pulse
@@WaitDE:
	in   al,dx
	test al,01h
	jnz  @@WaitDE            ;display enable is active low (0 = active)

	mov  dx,CRTC_INDEX
	mov  ax,bx
	cli
	out  dx,ax               ;start address low
	mov  ax,cx
	out  dx,ax               ;start address high
	sti

; Now wait for vertical sync, so the other page will be invisible when
; we start drawing to it.
	mov  dx,INPUT_STATUS_0    ;Wait for trailing edge of Vsync pulse
@@WaitVS:
	in   al,dx
	test al,08h
	jz @@WaitVS           ;display enable is active low (0 = active)


	mov  dx,AC_INDEX
	mov  ax,si                ; Point the attribute controller to pel pan
	cli
	out  dx,al                ; reg. Bit 5 also set to prevent blanking
	mov  al,ah
	out  dx,al                ; load new Pel Pan setting.
	sti

@@Return:
	mov  [_ErrorValue],OK
	pop  si
	pop  bp
	ret
_x_set_start_addr  endp


;-----------------------------------------------------------------------
; Mode X (256 color mode) Mode X split screen hide
; C near-callable as:
;
;    void x_hide_splitscreen()
;
; Hides an existing split screen by setting its starting scan line to
; the last physical screen scan line
;
; WARNING: Only to be used if SplitScrnLine has been previously called
; WARNING: DO NOT USE with mode 5-11 (320x400-376x564). The memory for
;          the initial split screen is reserved and the size limitations
;          of these modes means any change in the split screen scan line
;          will encroach on the split screen ram
;
; Written by Themie Gouthas
;------------------------------------------------------------------------

_x_hide_splitscreen proc
	push bp
	mov  bp,sp

	cmp  [_SplitScrnActive],TRUE
	je   @@SplitScreenEnabled

@@error:
	mov  [_ErrorValue],ERROR
	pop  bp
	ret

@@SplitScreenEnabled:
	cmp  [_CurrXMode],4          ; Do nothing for Modes > 2
	jg   @@error
	mov  bx,[_ScrnPhysicalHeight]

	mov  ax,[_ScrnLogicalHeight]
	sub  ax,bx
	mov  [_MaxScrollY],ax
	xor  ax,ax
	mov  [_SplitScrnVisibleHeight],ax

	or    [DoubleScanFlag],0
	jz    @@NotDoubleScanned
	shl   bx,1
	dec   bx
@@NotDoubleScanned:
	;mov  cl,[DoubleScanFlag]  ; Compensate for double scanned modes
	;shl  bx,cl

	WaitVsyncStart               ; wait for vertical retrace

	cli                 ; Dont allow register setting to be interrupted
	mov  dx,CRTC_INDEX
	mov  ah,bl
	mov  al,LINE_COMPARE
	out  dx,ax          ; Bits 7-0 of the split screen scan line

	mov  ah,bh
	and  ah,1
	shl  ah,4
	mov  al,OVERFLOW  ; Bit 4 of overflow register = Bit 8 of split
	out  dx,al        ; screen scan line,
	inc  dx           ; So using readability of VGA registers
	in   al,dx        ; Read the OVERFLOW register, and set the
	and  al, not 10h  ; bit corresponding to Bit 8 (above)
	or   al,ah
	out  dx,al

	dec  dx
	mov  ah,bh
	and  ah,2
	ror  ah,3
	mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =
	out  dx,al             ; Bit 9 of split screen scan line
	inc  dx                ; As we did before, update the apropriate
	in   al,dx             ; bit without disturbing the rest
	and  al, not 40h
	or   al,ah
	out  dx,al
	sti                  ; Registers are set, so interrupts are safe

@@done:

	mov  [_ErrorValue],OK
	pop  bp
	ret
_x_hide_splitscreen endp

;-----------------------------------------------------------------------
; Mode X (256 color mode) Mode X split screen show
; C near-callable as:
;
;    void x_show_splitscreen()
;
; Restores split screen start scan line to the initial split screen
; starting scan line as set by SplitScrnLine.
;
; WARNING: Only to be used if SplitScrnLine has been previously called
; WARNING: DO NOT USE with mode 5-11 (320x400-376x564). The memory for
;          the initial split screen is reserved and the size limitations
;          of these modes means any change in the split screen scan line
;          will encroach on the split screen ram
;          Update: Now disabled for these modes
;
; Written by Themie Gouthas
;------------------------------------------------------------------------


_x_show_splitscreen proc
	push bp
	mov  bp,sp

	cmp  [_SplitScrnActive],TRUE
	je   @@SplitScreenEnabled

@@error:
	mov  [_ErrorValue],ERROR
	pop  bp
	ret

@@SplitScreenEnabled:
	cmp  [_CurrXMode],4          ; Do nothing for Modes > 2
	jg   @@error

	mov  bx,[_SplitScrnScanLine]
	mov  ax,[_ScrnLogicalHeight] ; Update Max Scroll Y

⌨️ 快捷键说明

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