1 ;; ====================================================================
\r
3 ;; ====================================================================
\r
4 ;; Jump if key pressed
\r
5 JKEYP MACRO key,label
\r
6 cmp byte ptr cs:_keyFlags[key+1],1
\r
9 ;; Jump if key not pressed
\r
10 JKEYNP MACRO key,label
\r
11 cmp byte ptr cs:_keyFlags[key+1],1
\r
15 ;; Note that JNKEY and JKEY both modify _flKeyChanged, so you cannot
\r
16 ;; use one after the other! In other words,
\r
18 ;; JKEYP yes_key ;<-- this will fail
\r
19 ;; will not work like you'd think it would. The second call (JKEYP)
\r
20 ;; will not know that a key has been pressed!
\r
21 ;; Jump if no key pressed:
\r
23 cmp cs:_flKeyChanged,0
\r
25 mov cs:_flKeyChanged,0 ; <--- important!
\r
27 ;; Jump if key pressed:
\r
29 cmp cs:_flKeyChanged,0
\r
30 mov cs:_flKeyChanged,0
\r
34 ;; Start keyboard interrupts
\r
37 mov cs:_flKeyChanged,0
\r
40 ;; Clear keyboard interrupts
\r
45 ;; Credit for these routines: Steve Dollins, Brown Computer Group.
\r
46 ;; I didn't write any of the code below -- just heisted it from some
\r
47 ;; stuff that he wrote and released! Very useful keyboard routines.
\r
48 ;; Any comments prefixed SDE were added by me.
\r
49 _keyFlags dw 256 dup (0) ; SDE: since they only use 2 bits
\r
50 ; per word, this is a tradeoff,
\r
53 oldint9_offset dw offset newint9
\r
54 oldint9_segment dw seg newint9
\r
58 ;-----------------------------------------------------------------------
\r
59 ; void SwapInt9( void )
\r
61 ; SwapInt9() exchanges the vector in oldint9_segment:oldint9_offset
\r
62 ; with the vector in the interrupt table for INT 9h.
\r
63 ;-----------------------------------------------------------------------
\r
69 mov ax,03509h ; Get interrupt 09h
\r
70 int 21h ; return in ES:BX
\r
72 mov ax,oldint9_segment
\r
73 mov dx,oldint9_offset
\r
76 mov ax,02509h ; Set new interrupt
\r
77 int 21h ; to address in DS:DX
\r
80 mov oldint9_segment,es ; Save the old interrupt
\r
81 mov oldint9_offset,bx
\r
86 ;-----------------------------------------------------------------------
\r
87 ; newint9 is the new keyboard interrupt (INT 9h).
\r
89 ; Reads the scan code from the keyboard and modifies the key
\r
90 ; flags table. The high byte is set to the position of the key,
\r
91 ; pressed=1, release=0. The low byte is set to 1 when the key
\r
92 ; is pressed and left unmodified when the key is released.
\r
93 ;-----------------------------------------------------------------------
\r
102 JKEYNP kCTRL,not_ctrlaltdel ; SDE code
\r
103 JKEYNP kALT,not_ctrlaltdel ; To still allow ctrl-
\r
104 JKEYNP kDELETE,not_ctrlaltdel ; alt-delete. Nothing
\r
105 jmp ctrlaltdel ; worse than a total lockup!
\r
108 in ax,60h ; get scan code in AL, control byte in AH
\r
109 mov bx,ax ; save a copy in BX
\r
110 xchg ah,al ; swap to get control byte in AL
\r
111 or al,80h ; clear keyboard
\r
112 out 61h,al ; of interrupt
\r
115 mov al,20h ; send generic EOI to
\r
118 and bx,0007fh ; strip all but the scan code
\r
119 shl bx,1 ; multiply by two to get our offset
\r
121 ; if the key was released, the high bit is set in the scan code
\r
122 bt ax,15 ; move this high bit into the carry flag
\r
123 setnc byte ptr [_keyFlags+bx+1] ; set "Is being pressed" flag
\r
124 jc short int09done ; if the key was released, we're done
\r
125 mov byte ptr [_keyFlags+bx],1 ; set "Has been pressed" flag
\r
126 mov _flKeyChanged,1 ; state of keyboard has changed
\r
128 mov _flKeyChanged,1 ; state of keyboard has changed
\r
133 ctrlaltdel: int 19h ; SDE -- added this.
\r
137 ;; Defines the current key procedure (used as a jump-through)
\r
138 kprocCur dw KprocDirect
\r
140 ;; This is a keyboard procedure. Normally, this would control some
\r
141 ;; sprite, or something, and the screen would follow the sprite. For
\r
142 ;; the purposes of this code, though (namely, sprite-less scrolling)
\r
143 ;; it just directly affects ScrollDX and ScrollDY.
\r
144 ;; This keyproc is inertialess, use + and - to increase speed and
\r
145 ;; the up/down/left/right keys to move directions.
\r
146 ;; Pressing K will switch to the other keyprocedure on the fly.
\r
147 ;; P pauses the screen -- note that this is just for completely
\r
148 ;; freezing the screen... it doesn't return until you let go!
\r
151 scroll_speed_x dw SCROLL_SPEED ; (defaults)
\r
152 scroll_speed_y dw SCROLL_SPEED * VIRTUAL_WIDTH ; (defaults)
\r
153 KprocDirect PROC near
\r
154 chk_leftright: mov ax,0
\r
155 JKEYNP kRIGHT,not_right
\r
156 mov ax,scroll_speed_x
\r
159 not_right: JKEYNP kLEFT,not_left
\r
160 sub ax,scroll_speed_x
\r
163 not_left: mov ScrollDX,ax
\r
165 chk_updown: mov ax,0
\r
167 sub ax,scroll_speed_y
\r
170 not_up: JKEYNP kDOWN,not_down
\r
171 mov ax,scroll_speed_y
\r
174 not_down: mov ScrollDY,ax
\r
176 chk_other: JKEYNP kK,not_k
\r
177 mov kprocCur,KprocInertia
\r
178 not_k: JKEYNP kM,not_m
\r
179 mov bDoTransition,1
\r
180 not_m: JKEYNP kGREY_MINUS,not_minus
\r
181 cmp scroll_speed_x,1
\r
184 sub scroll_speed_y,VIRTUAL_WIDTH
\r
185 not_minus: JKEYNP kGREY_PLUS,not_plus
\r
186 cmp scroll_speed_x,16
\r
189 add scroll_speed_y,VIRTUAL_WIDTH
\r
192 pause_key: JKEYP kP,pause_key
\r
197 ;; This keyproc has inertia, so + and - don't work.
\r
198 ;; Use up/down/left/right keys to increase speed in those directions.
\r
199 ;; Pressing K will switch to the other keyprocedure on the fly.
\r
200 ;; P pauses the screen -- note that this is just for completely
\r
201 ;; freezing the screen... it doesn't return until you let go!
\r
202 KprocInertia PROC near
\r
203 chk2_leftright: JKEYNP kRIGHT,not2_right
\r
208 not2_right: JKEYNP kLEFT,not2_left
\r
215 chk2_updown: JKEYNP kUP,not2_up
\r
216 cmp ScrollDY,-VIRTUAL_WIDTH * 16
\r
218 add ScrollDY,-VIRTUAL_WIDTH
\r
220 not2_up: JKEYNP kDOWN,not2_down
\r
221 cmp ScrollDY,VIRTUAL_WIDTH * 16
\r
223 add ScrollDY,VIRTUAL_WIDTH
\r
227 chk2_other: JKEYNP kK,not2_k
\r
228 mov kprocCur,KprocDirect
\r
229 not2_k: JKEYNP kM,not2_m
\r
230 mov bDoTransition,1
\r
233 pause2_key: JKEYP kP,pause2_key
\r