📄 plane.asm
字号:
JNZ Y_COUNT_DOWN
;Increment counter in loop. Cursor movement is down
Y_DOWN:
CMP CROSS_Y,CUR_LIM_DOWN ;Equate for bottom limit of move
JA NO_DOWN_Y ;No down movement of cursor
INC CROSS_Y ;Bump counter if not at limit
LOOP Y_DOWN
NO_DOWN_Y:
RET
;Decrement counter to move cursor up
Y_COUNT_DOWN:
MOV CH,0 ;Clear high-order byte of counter
NOT CL ;Convert 2's complement value
INC CL ;To unsighed binary
Y_UP:
CMP CROSS_Y,CUR_LIM_UP ;Equate for left hand limit
JB NO_UP
DEC CROSS_Y
LOOP Y_UP
NO_UP:
RET
UPDATE_Y ENDP
;******************************************************************************************
XOR_XHAIR PROC NEAR
CALL DATA_XOR
;XOR cross-hair symbol. If symbol displayed, erase, and vice versa
CLI ;Interrput off
PUSH CX ;Save mickey registers
PUSH DX
MOV SI,OFFSET CROSS_X ;Offset of display block
MOV BX,OFFSET CR_COL ;Offset of color table
CALL TIME_VRC ;Time display with vertical retrace
CALL VARI_PATTERN ;Display routine
STI ;Interrput in
CALL DATA_NORMAL
POP DX ;Restore mickey count
POP CX
RET
XOR_XHAIR ENDP
;==========================================================================================
;Test for start of the vertical retrace cycle of the CRT
;Controller Bit 7 of input status register 0 is set if a vertical cycle is in process
;==========================================================================================
TIME_VRC PROC NEAR
MOV DX,3DAH ;Input status register 0
;In VGA color modes
VRC_CLEAR:
IN AL,DX ;Read byte at port
JMP SHORT $+2 ;I/O delay
TEST AL,00001000B ;Is bit 3 set?
JNZ VRC_CLEAR
;At this point the vertical retrace ended. Wait for it to restart
VRC_START:
IN AL,DX ;Read byte at port
JMP SHORT $+2 ;I/O delay
TEST AL,00001000B ;Is bit 3 set?
JZ VRC_START ;Wait untill bit set
RET
TIME_VRC ENDP
;==========================================================================================
SCOREBOARD PROC NEAR
;Update program's scoreboard using the values in the variables
;First update rounds left
;==========================================================================================
MOV DL,FIRE_CNT ;Binary count of rounds remaining
MOV DH,0 ;Clear high-order byte
LEA DI,NUM_BUFFER ;Buffer for 5 digits
CALL BIN_TO_ASC ;Convert to ASCII decimal number
;Buffer holds 2 valid ASCII digits. DI -> start of buffer
XCHG SI,DI ;Invert SI and DI
ADD SI,3 ;Point to first significant digit
LEA DI,LEFT ;Point to destination
MOV CX,2 ;Number of digits to move
CALL MOVE_CX_DIGS ;Auxiliary procedure
MOV DL,10
SUB DL,FIRE_CNT
MOV DH,0
LEA DI,NUM_BUFFER
CALL BIN_TO_ASC
XCHG SI,DI
ADD SI,3
LEA DI,FIRED
MOV CX,2
CALL MOVE_CX_DIGS
;Update display
MOV PLANE_OFF,1
CALL DATA_NORMAL ;Procedure from 10.4.1.2
MOV AL,2
CALL SET_WRITE_MODE ;Procedure from 10.3.1
;Draw blue area for scoreboard
MOV CH,21 ;Start column
MOV CL,38 ;Start row
MOV DH,39 ;Horizontal bytes
MOV DL,2 ;Vertical bytes
MOV AL,1 ;Blue
CALL COARSE_FILL ;Procedure from 10.3.3
MOV AL,0 ;Write mode 0 for text display
CALL SET_WRITE_MODE
LEA DI,DATA_LN ;Scoreboard variable text line
CALL GRAPHIC_TEXT ;Procedure from 10.3.2
MOV AL,2
CALL SET_WRITE_MODE ;Write mode 2 for graphics display
MOV PLANE_OFF,0
RET
SCOREBOARD ENDP
;==========================================================================================
GET_SCORE PROC NEAR
;Calculate game number and score and set in display area
MOV DL,GAME_CNT ;Binary game count
MOV DH,0 ;Clear high-order byte
LEA DI,NUM_BUFFER ;Buffer for 5 digits
CALL BIN_TO_ASC ;Conversion procedure
;Buffer holds 2 valid ASCII digits. DI -> start of buffer
XCHG SI,DI ;Invert SI and DI
ADD SI,3 ;Point to first significant digit
LEA DI,GAME ;Point to destination
MOV CX,2 ;Number of digits to move
CALL MOVE_CX_DIGS ;Auxiliary procedure
MOV DL,SCORE_CNT ;Binary score counter
MOV DH,0 ;Clear high-order byte
LEA DI,NUM_BUFFER ;Buffer for 5 digits
CALL BIN_TO_ASC ;Conversion procedure
;Buffer holds 2 valid ASCII digits. DI -> START OF BUFFER
XCHG SI,DI ;Invet SI and DI
ADD SI,2 ;Point to first significant digit
LEA DI,SCORE ;Point to destination
MOV CX,3 ;Number of digits to move
CALL MOVE_CX_DIGS ;Auxiliary procedure
RET
GET_SCORE ENDP
;==========================================================================================
MOVE_CX_DIGS PROC NEAR
;Auxiliary procedure to move a given number of digits into a buffer
;On entry:
; SI -> SOURCW HOLDING DIGITS
; DI -> destination for digits
; CX -> number of digits to move
;Note: A block move is not convenient because ES is used as a video buffer pointer
MOVE_DIGITS:
MOV AL,[SI] ;Get source digit
MOV [DI],AL ;Place in destination
INC SI ;Bump buffer pointers
INC DI
LOOP MOVE_DIGITS
RET
MOVE_CX_DIGS ENDP
;------------------------------------------------------------------------------------------
BIN_TO_ASC PROC NEAR
;Convert a 16-bit binary in the DX register to an ASCII decimal number
;On entry:
; DX = binary source
; DI -> 5-byte output buffer
;On exit:
; DI -> start of buffer holding the ASCII decimal number
;------------------------------------------------------------------------------------------
PUSH DI ;Save start of buffer
MOV CX,5 ;5 digits to clear
CLEAR_BUF:
MOV BYTE PTR [DI],20H ;Clear digit
INC DI ;Bump pointer
LOOP CLEAR_BUF ;Repeat for 5 digits
DEC DI ;Adjust buffer pointer to last digit
BINA0:
MOV AX,DX ;Add in numerator
MOV DX,0 ;Clear top half
MOV CX,10 ;Enter decimal divisor
DIV CX ;Perform division AX/CX
XCHG AX,DX ;Get quotient
ADD AL,30H ;Make digit ASCII
MOV [DI],AL ;Store digit in buffer
DEC DI ;Bump desination pointer
CMP DX,0 ;Test for end of binary
JNZ BINA0 ;Continue if not end
POP DI ;Restore pointer to start of buffer
RET
BIN_TO_ASC ENDP
;******************************************************************************************
;INT 1CH handler--------timer interrupt
;The following routine moves the PLANE one step (4 pixels) horizontally.
;The routine executes at every timer interrput,which is approximately
;18.2 times per second
;******************************************************************************************
HEX1C_INT:
CLI ;Interrupt off
PUSH AX ;Save context at interrupt time
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
PUSH DS
PUSH ES
;Bit 3 of status register 0 is set if a vertical retrace interrputs has occurred
MOV DX,3DAH ;Input status register
IN AL,DX ;Read byte at port
JMP SHORT $+2 ;I/O delay
TEST AL,00001000B ;Is bit 3 set?
JE VRI ;Go if vertical retrace
;Chain to next handler
POP ES ;Restore context at interrput time
POP DS
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX
STI ;Continue processing
IRET
VRI: MOV AX,DATA
MOV DS,AX
;Test for PLANE display suspended
CMP DS:PLANE_OFF,1 ;No PLANE display
JE EXIT_PLANE ;Display PLANE if switch off
CMP HIT_SW,1
JNZ SHOW_PLANE
MOV BX,100
CALL RANDOM_NUM
ADD DX,360
MOV DS:PLANE_Y,DX
MOV HIT_SW,0
MOV FIRST_PLANE,1
;jmp PLANE_on
SHOW_PLANE:
MOV AX,0A000H ;EAG/VGA systems base address
MOV ES,AX ; to ES
;Test for zero x coordinate
CMP DS:PLANE_X,620 ;No display if coordinate=0
JE EXIT_PLANE ;Exit routine
;Move PLANE left
CMP DS:PLANE_X,617 ;Left side limit
JB PLANE_DISPLAY
;Start at new line
CALL XOR_PLANE ;Erase PLANE
MOV DS:FIRST_PLANE,1 ;Set first PLANE displayed switch
MOV DS:PLANE_X,0 ;PLANE back to right screen side
;The PLANE appears at random between screen pixel rows 362 and 462
MOV BX,100 ;Range of random number is 0 to 100
CALL RANDOM_NUM ;Get random value for y coordinate
;DX has random number
ADD DX,360 ;Move to screen range
MOV DS:PLANE_Y,DX ;Store in display variable
PLANE_DISPLAY:
CMP DS:FIRST_PLANE,1
JE PLANE_ON ;Turn on PLANE
CALL XOR_PLANE
ADD DS:PLANE_X,PLANE_SPEED ;Decrement cursor position
CALL XOR_PLANE ;Display new cursor
JMP EXIT_PLANE
PLANE_ON:
MOV DS:FIRST_PLANE,0 ;Trun off first iteration switch
CALL XOR_PLANE
EXIT_PLANE:
POP ES ;Restore context
POP DS
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX
STI ;Interrupts on
IRET
;------------------------------------------------------------------------------------------
XOR_PLANE PROC NEAR
CALL DATA_XOR
;
CLI
PUSH CX
PUSH DX
;This procedure displays and erases the PLANE
MOV SI,OFFSET PLANE_X
MOV BX,OFFSET PLANE_COLOR
; call time_vrc
CALL VARI_PATTERN ;Procedure from 10.3.3
CALL DATA_NORMAL
STI
POP DX
POP CX
RET
XOR_PLANE ENDP
;------------------------------------------------------------------------------------------
RANDOM_NUM PROC NEAR
;Random number generator using channel 0 of the system timer
;The random number is generated using the shift register algorithm
;On entry:
; BX = high value of range desired, for example,to obtain a random number
; in the range 0 to 100, BX will hold the value 100
; Lowest allowable range is 0 to 4
;On exit:
; DX = random number in range
;------------------------------------------------------------------------------------------
;Read timer channel 0 at port 40H
MOV AL,00000110B
OUT 43H,AL ;To counter command port
JMP SHORT $+2 ;I/O delay
;Read LSB then MSB
IN AL,40H ;Read LSB
JMP SHORT $+2
MOV DL,AL
;*****
MOV DH,0
;*****
;IN AL,DX ;DX = value in timer latch ;<<<*****edited******>>>
MOV DH,AL
;Shift register algorithm
RESCALE:
MOV AX,DX ;Copy value in AX
MOV CL,3 ;Shift right 3 digits
SAR AX,CL
ADD AX,DX ;Add with no carry
MOV CL,4 ;Value to shift left
SAL AX,CL ;Shift left
ADD AX,DX ;Add again
;Dividing by the upper limit of the range will generate a remainder less than this limit
MOV DX,0 ;Use value in AX
DIV BX ;Remainder is in DX
RET
RANDOM_NUM ENDP
;******************************************************************************************
;This mouse interrupt handler receives control when either mouse button is pressed
;******************************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -