Skip to content

Instantly share code, notes, and snippets.

@wraithgar
Created February 6, 2023 15:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wraithgar/0e849d73869756180fbd83ab811b24cf to your computer and use it in GitHub Desktop.
Save wraithgar/0e849d73869756180fbd83ab811b24cf to your computer and use it in GitHub Desktop.
nes pad DOS driver
.radix 16
org 100
clockoff equ 000000xb
pad_init equ 001001xb
pad_clockon equ 010010xb
pad_power equ 100100xb
a_mask equ 00000001xb
b_mask equ 00000010xb
select_mask equ 00000100xb
start_mask equ 00001000xb
up_mask equ 00010000xb
down_mask equ 00100000xb
left_mask equ 01000000xb
right_mask equ 10000000xb
pad macro
mov al,#1+pad_power
call do_pad
#em
jmp begin
intro db 0d
db 'NESPad! by GeorgeCo.'
db 1a
up_key db 00
up_make_len db 02
up_make_scan db 0e0, 48
up_break_len db 02
up_break_scan db 0e0, 0c8
down_key db 00
down_make_len db 02
down_make_scan db 0e0, 50
down_break_len db 02
down_break_scan db 0e0, 0d0
left_key db 00
left_make_len db 02
left_make_scan db 0e0, 4b
left_break_len db 02
left_break_scan db 0e0, 0cb
right_key db 00
right_make_len db 02
right_make_scan db 0e0, 4d
right_break_len db 02
right_break_scan db 0e0, 0cd
b_key db 00
b_make_len db 01
b_make_scan db 30
b_break_len db 01
b_break_scan db 0b0
a_key db 00
a_make_len db 01
a_make_scan db 1e
a_break_len db 01
a_break_scan db 9e
select_key db 00
select_make_len db 01
select_make_scan db 12
select_break_len db 01
select_scan db 92
start_key db 00
start_make_len db 01
start_make_scan db 14
start_break_len db 01
start_break_scan db 94
pastbtn db 00
buttons db 00
lpt_ptr dd 0040:0008
newint8:
jmp >L1
sign db 'NESPad'
rl8ofs dw 0000
rl8seg dw 0000
L1: pushf
cs:
call far rl8ofs ;do the real 08
busy: nop ;0cf=iret 090=nop
push ds
push si
push ax
push cx
push dx
push cs
pop ds
cld
mov al,buttons
mov pastbtn,al
call getstat ;see what the pad looks like
mov dl,buttons
xor dl,pastbtn
jz endint8 ;if no buttons changed, byebye
mov byte busy,0cf ;don't let it build up
test dl,a_mask
jz no_a
mov si,offset(a_key)
call do_key
no_a:
test dl,b_mask
jz no_b
mov si,offset(b_key)
call do_key
no_b:
test dl,select_mask
jz no_select
mov si,offset(select_key)
call do_key
no_select:
test dl,start_mask
jz no_start
mov si,offset(start_key)
call do_key
no_start:
test dl,up_mask
jz no_up
mov si,offset(up_key)
call do_key
no_up:
test dl,down_mask
jz no_down
mov si,offset(down_key)
call do_key
no_down:
test dl,left_mask
jz no_left
mov si,offset(left_key)
call do_key
no_left:
test dl,right_mask
jz no_right
mov si,offset(right_key)
call do_key
no_right:
mov byte busy,90
endint8:
pop dx
pop cx
pop ax
pop si
pop ds
iret
getstat:
push ds
pad pad_init ;turn both pads on
mov cx,08
statlp:
cs:
lds si,lpt_ptr
mov dx,[si]
inc dx
in al,dx
rcl al,0
cs:
rcr buttons,01
pad pad_clockon
pad clockoff
loop statlp
pop ds
ret
do_pad:
cs:
lds si,lpt_ptr
mov dx,[si]
out dx,al
nop
nop
nop
ret
do_key: ;or is it dookie?
xor ax,ax
xor cx,cx
not byte [si]
lodsb ;get key stat (up,down)
or al,al
jnz >L1 ;it's been notted
lodsb
add si,ax ;skip make scancodes
L1: lodsb ;get number of scancodes
mov cl,al
L2:
mov al,0d2
out 64,al
lodsb
out 60,al ;only works on ps/2
loop L2
ret
intend:
helpmsg db 'NesPad! by GeorgeCo.'
db 0d, 0a
db 'Use /T to test pad'
db 0d, 0a
db 'Use /U to unload'
db 0d, 0a
db 'NesPad! defaults to LPT1. To change to another,'
db 0d, 0a
db 'use /2 for LPT2, /3 for LPT3, and /4 for LPT4.'
db 0d, 0a
db 'For test mode, /2 /3 or /4 must precede /T$'
ldmsg db 'NesPad! is now loaded'
db 0d, 0a
db 'Use /? for help'
db 0d, 0a
db 'Use /U to unload$'
inmem db 'NESPad! already loaded$'
nosfnd db 'Memory clean$'
ulmsg db 'NESPad! found, cleaned$'
kbderr db 'Keyboard does not support NesPad!$'
crlf db 0d, 0a, 24
cursor dw ?
us dw ?
them dw ?
post_data db 0d, 0a
db '| | | | | | | |'
db 0d, 0a
db 'A B S S U D L R'
db 0d, 0a
db ' e t p o e i'
db 0d, 0a
db ' l a w f g'
db 0d, 0a
db ' e r n t h'
db 0d, 0a
db ' c t t'
db 0d, 0a
db ' t$'
begin: mov si,0080
lodsb ;get len of comlin
or al,al
jz nocmln
xor cx,cx
mov cl,al
parse: lodsb
or al,20 ;force lowercase
cmp al,'u' ;see if we're to unload
jz >L3
cmp al,'t'
jz >L1
cmp al,'?'
jz >L2
cmp al,'2'
jz lpt2
cmp al,'3'
jz lpt3
cmp al,'4'
jz lpt4
loop parse
L2: mov dx,offset(helpmsg)
call do_prn
mov ax,4c00
int 21
L3: jmp unload
L1: jmp pad_test
lpt4: inc word lpt_ptr
inc word lpt_ptr
lpt3: inc word lpt_ptr
inc word lpt_ptr
lpt2: inc word lpt_ptr
inc word lpt_ptr
loop parse
nocmln: call chkey ;no comlin, check if already loaded
jnz ok2ld
mov dx,offset(inmem)
L1:
call do_prn
mov ax,4c01
int 21
nops2: mov dx,offset(kbderr)
jmp L1
ok2ld:
;check that the key emulating method works
mov ah,22
call key_stuff
or ah,80
call key_stuff
call get_key
cmp al,'g'
jnz nops2
mov ah,2e
call key_stuff
or ah,80
call key_stuff
call get_key
cmp al,'c'
jnz nops2
mov dx,offset(ldmsg) ;no, just load and say hi
call do_prn
mov ax,3508
int 21
mov rl8seg,es
mov rl8ofs,bx
mov ax,2508
mov dx,offset(newint8)
int 21
mov ah,49
mov es,[002c]
int 21 ;free environment segment
mov dx,offset(intend)+1
int 27
unload: call chkey
jz sfnd
mov dx,offset(nosfnd)
call do_prn ;print status
mov ax,4c00
int 21 ;exit w/ code 0
sfnd: mov ax,2508 ;if here, NESPad is int08
mov ds,them
lds dx,[di]
int 21 ;restore int 08
cs:
mov ds,us
mov ah,49
mov es,them
int 21 ;free mem
mov dx,offset(ulmsg)
call do_prn ;print status
jmp unload
pad_test:
call clr
mov ah,03
mov bh,00
int 10 ;save the old cursor
mov cursor,bx
mov ah,01
mov cx,2000
int 10 ;get rid of the cursor
tloop:
mov ah,02
mov bh,00
xor dx,dx
int 10
call getstat
mov cx,0008
L2:
mov al,31
rcr buttons,01
jc >L1
dec al
L1: mov ah,0e
int 10
mov ax,0e20
int 10
mov ax,0e20
int 10
loop L2
mov dx,offset(post_data)
call do_prn
mov ah,01
int 16
jz tloop
xor ax,ax
int 16
mov ah,01
mov cx,cursor
int 10 ;restore the cursor
mov ax,4c00
int 21
clr:
push ds
xor ax,ax
mov ds,ax ;ds points to BIOS segment
mov ax,0600 ;scroll window up (clear window)
mov bh,07 ;bh is attrib to use (white on black)
xor cx,cx ;cx=row,col of u-l corner of window
mov dl,[044a] ;dx=screen width in text columns
mov dh,[0484] ;dh=character rows-1
int 10 ;clear window from ch,cl to dh,dl
mov ah,02
mov bh,[0462] ;bh=current active video page
xor dx,dx
int 10 ;set cursor to 0,0
pop ds
ret
key_stuff:
mov al,0d2
out 64,al
mov al,ah
out 60,al
ret
get_key:
mov ah,01
int 16
jz >L1
xor ah,ah
int 16
L1: ret
chkey: mov ax,3508 ;get int08 in es:bx
int 21
push ds
mov them,es
mov us,ds
mov di,bx
add di,02
mov si,offset(sign)
mov cx,0006
rep cmpsb ;check for signature
pop ds
ret
do_prn:
call prn@dx
prncrlf:
mov dx,offset(crlf)
prn@dx:
mov ah,09
int 21
ret
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment