I'm a beginner so this code probably isn't any good, I used int 16h
for this but I don't know a lot about this int
. I just found out you can't have multiple keystrokes at once; any help?
The problem with this code is that only one board can move at a time and I need both. How do I check for multiple inputs?
Here's the code for anyone who wants it:
IDEAL MODEL small STACK 100h DATASEG ; -------------------------- ; Your variables here ; -------------------------- line1X dw 80 line1Y dw 120 line1start dw 5 line1end dw 10 line2X dw 80 line2Y dw 120 line2start dw 310 line2end dw 315 CODESEG proc startVideo ;creates video mode mov al,13h mov ah,0h int 10h ret endp startVideo proc clearScrean ;turns the screen black mov ah, 0ch xor al,al mov dx,200 BlankLine: mov cx,320 BlankColumn: int 10h Loop BlankColumn dec dx cmp dx,0 jne BlankLine ret endp clearScrean proc drawboard ;creates the board push bp mov bp,sp mov al,0fh mov ah,0ch beginning equ [bp+10] fn equ [bp+8] X equ [bp+6] ;boards start Y equ [bp+4] ;boards end mov dx,Y drawrow: mov cx,fn drawcolumn: int 10h dec cx cmp cx,beginning jne drawcolumn dec dx cmp dx,X jne drawrow pop bp ret 8 endp drawboard proc drawall push [line1start] push [line1end] push [line1X] push [line1Y] call drawboard push [line2start] push [line2end] push [line2X] push [line2Y] call drawboard ret endp drawall proc boardup push bp mov bp,sp mov bx,[bp+4] mov si,[bp+6] cmp [word ptr bx],0 ;checks if board didnt get to border je fn1 call clearScrean sub [word ptr bx],5 ;3 pixels added to board sub [word ptr si],5 call drawall ;prints both boards fn1: pop bp ret 4 endp boardup proc boarddown push bp mov bp,sp mov bx,[bp+4] mov si,[bp+6] cmp [word ptr si],200 ;checks if board didnt get to border je fn2 call clearScrean add [word ptr bx],5 ;3 pixels added to board add [word ptr si],5 call drawall ;prints both boards fn2: pop bp ret 4 endp boarddown start: mov ax, @data mov ds, ax mov bh,0 call startVideo call clearScrean call drawall checkskey: ;checks if key is being pressed mov ah,1 int 16h jz checkskey ;jumps if key isnt pressed mov ah,0 ;checks which key is pressed int 16h cmp ah,11h ;if key pressed is w jump to upboard je upboard1 cmp ah,01fh ;if key pressed is s jump to downboard je downboard1 cmp ah,050h je downboard2 cmp ah,048h je upboard2 jmp checkskey ;if key isnt pressed jump to check key upboard1: ;board 1 goes up push offset line1Y push offset line1X call boardup jmp checkskey downboard1: ;board 1 goes down push offset line1Y push offset line1X call boarddown jmp checkskey downboard2: push offset line2Y push offset line2X call boarddown jmp checkskey upboard2: push offset line2Y push offset line2X call boardup jmp checkskey exit: mov ax, 4c00h int 21h END start
The other answer deals with a multi-player game where none of the players keep pushing their dedicated keys and thus hogging the keyboard. Although this scenario is quite reasonable, you might want to allow the players to hold their key down for a longer period. To this effect we can substitute the keyboard handler that BIOS/DOS provides by a handler of our own.
With each key on the keyboard is associated a unique 8-bit number we call the scancode.
Whenever a key is pressed the keyboard makes the scancode of the concerned key available at port 60h. The keyboard also generates an interrupt 09h. A handler for this interrupt can examine the scancode and process it in any way it likes. That's what the below demonstration program does.
When a key is pressed the scancode is a byte with its highest bit off. When a key is released the scancode is a byte with its highest bit on. The other 7 bits remain the same for both presses and releases.
It should be noted that, although fine for the purpose of your pong game, the included substitution handler is a minimalistic one. A sophisticated handler would also take into account the extended scancodes that are prefixed with an E0h or E1h code.
The program has additional comments so you can easily understand what's happening. The code uses FASM syntax. The demo runs OK in the real DOS environment and in the DOSBox (0.74).
; Multi-player Keyboard Input (c) 2021 Sep Roland
ORG 256 ; Output will be a .COM program
mov ax, 3509h ; DOS.GetInterruptVector
int 21h ; -> ES:BX
push es bx ; (1)
mov dx, Int09
mov ax, 2509h ; DOS.SetInterruptVector
int 21h
mov ax, 0013h ; BIOS.SetVideoMode 320x200 (256 colors)
int 10h
mov ax, 0A000h ; Video buffer
mov es, ax
cld ; So we can use the string primitive STOSB
Cont:
mov si, 160 ; Width
mov di, 100 ; Height
mov al, 0 ; Black
cmp [KeyList+48h], al ; Up
je .a
mov al, 2 ; Green
.a: mov cx, 160 ; X
mov dx, 0 ; Y
call Paint
mov al, 0 ; Black
cmp [KeyList+50h], al ; Down
je .b
mov al, 14 ; Yellow
.b: mov cx, 160 ; X
mov dx, 100 ; Y
call Paint
mov al, 0 ; Black
cmp [KeyList+11h], al ; aZerty / qWerty
je .c
mov al, 4 ; Red
.c: mov cx, 0 ; X
mov dx, 0 ; Y
call Paint
mov al, 0 ; Black
cmp [KeyList+1Fh], al ; S
je .d
mov al, 1 ; Blue
.d: mov cx, 0 ; X
mov dx, 100 ; Y
call Paint
cmp byte [KeyList+1], 0 ; ESC
je Cont
pop dx ds ; (1)
mov ax, 2509h ; DOS.SetInterruptVector
int 21h
mov ax, 4C00h ; DOS.Terminate
int 21h
; --------------------------------------
Int09:
push ax bx
in al, 60h
mov ah, 0
mov bx, ax
and bx, 127 ; 7-bit scancode goes to BX
shl ax, 1 ; 1-bit press/release goes to AH
xor ah, 1 ; -> AH=1 Press, AH=0 Release
mov [cs:KeyList+bx], ah
mov al, 20h ; The non specific EOI (End Of Interrupt)
out 20h, al
pop bx ax
iret
; --------------------------------------
; IN (al,cx,dx,si,di)
Paint:
push cx dx di ; AL=Color CX=X DX=Y SI=Width DI=Height
push ax ; (1)
mov ax, 320 ; BytesPerScanline
mul dx
add ax, cx ; (Y * BPS) + X
mov dx, di
mov di, ax
pop ax ; (1)
.a: mov cx, si
rep stosb
sub di, si
add di, 320
dec dx
jnz .a
pop di dx cx
ret
; --------------------------------------
KeyList db 128 dup 0
KeyList db 128 dup 0
The program's KeyList records the current state of all of the keys on the keyboard. If a byte is 0, the key is not being pressed. If a byte is 1, that key is currently being pressed.