Copy Link
Add to Bookmark
Report

How to use a Jaguar Powerpad with an Atari computer

DrWatson's profile picture
Published in 
atari
 · 11 months ago

JAGUAR POWERPAD HANDLER

Coded By Mr Pink

- RESERVOIR GODS 1995 -

If you have an STE or Falcon and are writing games software, it is a good idea to support the Jaguar Powerpads which can be plugged in via the extended controller ports. Not only are these easier to access than the fiddly joystick ports, it means you can have a more complex control method with 3 fire buttons and numerous other keys at your disposal.

If you have written some keyboard for the ST before, try to forget them as the extended controller ports work in a very different way from the rest of the keyboard. They are not in any way linked to the keyboard or the IKBD processor. They do no generate any interrupts (unlike a conventional keypress/mouse/joystick movement which will generate a keyboard interrupt). Because of this, you cannot put this routine on $118 and expect it to work. You have to physically interrogate the ports every vbl to get the current state of the powerpads plugged in.

Enquiring about the powerpad state is done via two hardware address: $ffff9200 and $ffff9202. A write mask is written to address $ffff9202 and then both addresses can be read as they will contain the selected powerpad data.

There are a total of 8 different write masks (4 for each powerpad) which have to be written to get every piece of powerpad data.

The data for Fire A, B & C, Pause and Option is returned in $ffff9200 whilst the other data (directional+keypad) is returned at $ffff9202.

When enquiring about powerpad A only bits 0-1 of $ffff9200 and bits 8-11 of $ffff9202 are relevant. When examining powerpad B only bits 2-3 of $ffff9200 and bits 12-15 of $ffff9202 are required.

As the routine accesses hardware addresses you must be in supervisor mode when you call, so ensure you have set into this mode (GEMDOS function $20) or use a supexec call (XBIOS $26)

My routine gleans all the information about the current state of the powerpads and creates two data packets from it.

The first is a byte packet which contains directional data and fire information.

The bit structure is:

-------------------- 
| Bit | Represents |
--------------------
| 0 | Up |
| 1 | Down |
| 2 | Left |
| 3 | Right |
| 4 | (not used) |
| 5 | Fire C |
| 6 | Fire B |
| 7 | Fire A |
--------------------

The second variable is a word that contains information about all the Powerpad keypad key as well as Pause and Option.

-------------------- 
| Bit | Represents |
--------------------
| 0 | * |
| 1 | 7 |
| 2 | 4 |
| 3 | 1 |
| 4 | 0 |
| 5 | 8 |
| 6 | 5 |
| 7 | 2 |
| 8 | # |
| 9 | 9 |
| 10 | 6 |
| 11 | 3 |
| 12 | Option |
| 13 | Pause |
--------------------

When reading from the extended controller ports, the flagging is different from other keyboard reports. A bit of 0 means the flagged key is on, a bit of 1 means it is off. I inverse this for my packets so a bit of 1 means a key is pressed whilst 0 means it is off. I find this a lot easier to remember!

An example:

move.w  jp1_key,d0              ;get powerpad a key info 
btst #13,d0 ;check pause flag
bne do_pause_routine ;pause pressed - do subroutine

You may be wondering about the strange order of the "key" packet. This is the order in which the keypad bits are returned. You could sort them out into numerical order in your powerpad handler but this is really an unnecessary waste of processor time. You can still easily check for each keypress, it is just a question of remembering which bit represents what.

I hope these routines may be of use in your future games and productions!

POWERPAD.S

*************************** 
* JAGUAR POWERPAD HANDLER *
** FOR ATARI STE/FALCON ***
**** CODED BY MR. PINK ****
* (C) 1995 RESERVOIR GODS *
***************************

; The routines to read powerpads A and B are separate.
; Each updates two variables, a directional byte and a key word.
; The directional byte contains information about the directions being
; pressed and the state of the fire buttons.
; The key word contains info about all the numeric keypad buttons
; and Pause and Option buttons.

; NOTE: You must be in supervisor mode to call these routines!
; You must either call them every vertical blank or put them on the vbl.

; DIRECTIONAL BYTE FORMAT
; -------------------
; Bit | Powerpad key
; ------------------
; 0 | Up
; 1 | Down
; 2 | Left
; 3 | Right
; 4 | (not used)
; 5 | Fire C
; 6 | Fire B
; 7 | Fire A

; KEY WORD FORMAT
; --------------
; Bit | Powerpad Key
; --------------
; 0 | *
; 1 | 7
; 2 | 4
; 3 | 1
; 4 | 0
; 5 | 8
; 6 | 5
; 7 | 2
; 8 | #
; 9 | 9
; 10 | 6
; 11 | 3
; 12 | Option
; 13 | Pause

read_powerpad_a:
lea $ffff9200.w,a0 ;extended port address (read only)
lea 2(a0),a1 ;extended port address (read/write)
moveq #0,d2 ;clear d2 - it will contain key information
move.w #$fffe,(a1) ;write mask
move.w (a1),d0 ;read directional data
move.w (a0),d3 ;read fire_a/pause data
not.w d0 ;invert bits (0->1)
move.w d0,d1 ;save directional data
lsr.w #8,d1 ;shift into low bits (0-3)
and.w #%1111,d1 ;mask off unwanted data
lsr.w d3 ;check bit 0 (pause data)
bcs.s no_pause_a ;if set, pause is not pressed
bset #13,d2 ;pause is pressed so set pause bit
no_pause_a:
lsr.w d3 ;check bit 1 (fire a data)
bcs.s no_firea_a ;if set, fire is not pressed
bset #7,d1 ;fire_a is pressed, so set fire_a bit
no_firea_a:
move.w #$fffd,(a1) ;write mask
move.w (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #1,d3 ;check fire_b
bne.s no_fireb_a ;if set, fire_b is not pressed
bset #6,d1 ;fire_b is pressed, set relevant bit
no_fireb_a:
lsr.w #8,d0 ;shift key data into bits 0-3
and.w #%1111,d0 ;mask off unwanted data
or.w d0,d2 ;store in key word

move.w #$fffb,(a1) ;write mask
move.w (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #1,d3 ;check for fire_c
bne.s no_firec_a ;if set, fire_c is not pressed
bset #5,d1 ;fire_c is pressed, set relevant bit
no_firec_a:
lsr.w #4,d0 ;shift key data into bits 4-7
and.w #%11110000,d0 ;mask off unwanted data
or.w d0,d2 ;store in key word

move.w #$fff7,(a1) ;write mask
move.w (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #1,d3 ;check for option
bne.s no_option_a ;if set, option is not pressed
bset #12,d2 ;set option bit
no_option_a:
and.w #%111100000000,d0 ;mask off unwanted bits
or.w d0,d2 ;store key data
move.b d1,jp1_dir ;save directional+fire data in variable
move.w d2,jp1_key ;save key data in variable
rts

read_powerpad_b:
lea $ffff9200.w,a0 ;extended port address (read only)
lea 2(a0),a1 ;extended port address (read/write)
moveq #0,d2 ;clear d2 - it will contain key information
move.w #$ffef,(a1) ;write mask
move.w (a1),d0 ;read directional data
move.w (a0),d3 ;read fire_a/pause data
not.w d0 ;invert bits (0->1)
move.w d0,d1 ;save directional data
lsr.w #8,d1 ;shift directional data down
lsr.w #4,d1 ;shift into low bits (0-3)
and.w #%1111,d1 ;mask off unwanted data
btst #2,d3 ;check bit 2 (pause data)
bne.s no_pause_b ;if set, pause is not pressed
bset #13,d2 ;pause is pressed so set pause bit
no_pause_b:
btst #3,d3 ;check bit 3 (fire a data)
bne.s no_firea_b ;if set, fire is not pressed
bset #7,d1 ;fire_a is pressed, so set fire_a bit
no_firea_b:
move.w #$ffdf,(a1) ;write mask
move.w (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #3,d3 ;check fire_b
bne.s no_fireb_b ;if set, fire_b is not pressed
bset #6,d1 ;fire_b is pressed, set relevant bit
no_fireb_b:
lsr.w #8,d0
lsr.w #4,d0 ;shift key data into bits 0-3
and.w #%1111,d0 ;mask off unwanted data
or.w d0,d2 ;store in key word

move.w #$ffbf,(a1) ;write mask
move.w (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #3,d3 ;check for fire_c
bne.s no_firec_b ;if set, fire_c is not pressed
bset #5,d1 ;fire_c is pressed, set relevant bit
no_firec_b:
lsr.w #8,d0 ;shift key data into bits 4-7
and.w #%11110000,d0 ;mask off unwanted data
or.w d0,d2 ;store in key word

move.w #$ff7f,(a1) ;write mask
move.w (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #3,d3 ;check for option
bne.s no_option_b ;if set, option is not pressed
bset #12,d2 ;set option bit
no_option_b:
lsr.w #4,d0 ;shift key data into bits 8-11
and.w #%111100000000,d0 ;mask off unwanted bits
or.w d0,d2 ;store key data
move.b d1,jp2_dir ;save directional+fire data in variable
move.w d2,jp2_key ;save key data in variable
rts

jp1_dir: ds.b 1
jp2_dir: ds.b 1
jp1_key: ds.w 1
jp2_key: ds.w 1

PPADTEST.S

*************************** 
* JAGUAR POWERPAD HANDLER *
** FOR ATARI STE/FALCON ***
***>>>>TEST PROGRAM<<<<****
**** CODED BY MR. PINK ****
* (C) 1995 RESERVOIR GODS *
***************************


; This is a little program to demonstrate the powerpad routines.
; It simply displays which buttons are currently being pressed
; on each powerpad.
; Press SPACE to quit

move.l a7,a5
move.l 4(a5),a5
move.l 12(a5),d0
add.l 20(a5),d0
add.l 28(a5),d0
add.l #$100,d0
move.l d0,-(a7)
move.l a5,-(a7)
move d0,-(a7)
move #$4a,-(a7)
trap #1
add.l #12,a7

clr.w -(a7)
pea $200000 ;supervisor mode
trap #1
bsr print_credits
bsr print_power_info

clr.w -(a7) ;term
trap #1


print_credits
lea credits_txt,a0
bsr print
wsp cmp.b #$39,$fffffc02.w
bne.s wsp
rts

print_power_info
bsr print_intro_txt
wait bsr read_powerpad_a
bsr read_powerpad_b
bsr print_dir_bits
cmp.b #$39,$fffffc02.w
bne.s wait
rts

print_dir_bits
move.b #34,cursor_y
move.b #34+10,cursor_x
move.b jp1_dir,d0
moveq #7,d1
bsr show_bits
move.w jp1_key,d0
move.w #13,d1
bsr show_bits

move.b #34,cursor_y
move.b #34+39,cursor_x
move.b jp2_dir,d0
moveq #7,d1
bsr show_bits
move.w jp2_key,d0
move.w #13,d1

show_bits
lsr.w d0
bcs.s do_on
bsr print_space
bra next_bit
do_on bsr print_on
next_bit
addq.b #1,cursor_y
dbra d1,show_bits
rts

print_intro_txt
lea clr_txt,a0
bsr print
lea txt_table,a6
next_txt
move.l (a6)+,a0
cmpa.w #0,a0
beq last_txt
move.b #32,cursor_x
bsr position_cursor
bsr print
move.b #32+30,cursor_x
bsr position_cursor
bsr print
addq.b #1,cursor_y
bra next_txt
last_txt
rts

print_on
bsr position_cursor
lea on_txt,a0
bra print

print_space
bsr position_cursor
lea space_txt,a0
bra print

position_cursor:
movem.l d0-2/a0-a2,-(a7)
pea pos_cursor_txt
bra.s prnt
print: movem.l d0-2/a0-2,-(a7)
pea (a0)
prnt: move.w #9,-(a7)
trap #1
addq.l #6,a7
movem.l (a7)+,d0-2/a0-2
rts

read_powerpad_a:
lea $ffff9200.w,a0 ;extended port address (read only)
lea 2(a0),a1 ;extended port address (read/write)
moveq #0,d2 ;clear d2 - it will contain key information
move.w #$fffe,(a1) ;write mask
move.w (a1),d0 ;read directional data
move.w (a0),d3 ;read fire_a/pause data
not.w d0 ;invert bits (0->1)
move.w d0,d1 ;save directional data
lsr.w #8,d1 ;shift into low bits (0-3)
and.w #%1111,d1 ;mask off unwanted data
lsr.w d3 ;check bit 0 (pause data)
bcs.s no_pause_a ;if set, pause is not pressed
bset #13,d2 ;pause is pressed so set pause bit
no_pause_a:
lsr.w d3 ;check bit 1 (fire a data)
bcs.s no_firea_a ;if set, fire is not pressed
bset #7,d1 ;fire_a is pressed, so set fire_a bit
no_firea_a:
move.w #$fffd,(a1) ;write mask
move.w (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #1,d3 ;check fire_b
bne.s no_fireb_a ;if set, fire_b is not pressed
bset #6,d1 ;fire_b is pressed, set relevant bit
no_fireb_a:
lsr.w #8,d0 ;shift key data into bits 0-3
and.w #%1111,d0 ;mask off unwanted data
or.w d0,d2 ;store in key word

move.w #$fffb,(a1) ;write mask
move.w (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #1,d3 ;check for fire_c
bne.s no_firec_a ;if set, fire_c is not pressed
bset #5,d1 ;fire_c is pressed, set relevant bit
no_firec_a:
lsr.w #4,d0 ;shift key data into bits 4-7
and.w #%11110000,d0 ;mask off unwanted data
or.w d0,d2 ;store in key word

move.w #$fff7,(a1) ;write mask
move.w (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #1,d3 ;check for option
bne.s no_option_a ;if set, option is not pressed
bset #12,d2 ;set option bit
no_option_a:
and.w #%111100000000,d0 ;mask off unwanted bits
or.w d0,d2 ;store key data
move.b d1,jp1_dir ;save directional+fire data in variable
move.w d2,jp1_key ;save key data in variable
rts

read_powerpad_b:
lea $ffff9200.w,a0 ;extended port address (read only)
lea 2(a0),a1 ;extended port address (read/write)
moveq #0,d2 ;clear d2 - it will contain key information
move.w #$ffef,(a1) ;write mask
move.w (a1),d0 ;read directional data
move.w (a0),d3 ;read fire_a/pause data
not.w d0 ;invert bits (0->1)
move.w d0,d1 ;save directional data
lsr.w #8,d1 ;shift directional data down
lsr.w #4,d1 ;shift into low bits (0-3)
and.w #%1111,d1 ;mask off unwanted data
btst #2,d3 ;check bit 2 (pause data)
bne.s no_pause_b ;if set, pause is not pressed
bset #13,d2 ;pause is pressed so set pause bit
no_pause_b:
btst #3,d3 ;check bit 3 (fire a data)
bne.s no_firea_b ;if set, fire is not pressed
bset #7,d1 ;fire_a is pressed, so set fire_a bit
no_firea_b:
move.w #$ffdf,(a1) ;write mask
move.w (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #3,d3 ;check fire_b
bne.s no_fireb_b ;if set, fire_b is not pressed
bset #6,d1 ;fire_b is pressed, set relevant bit
no_fireb_b:
lsr.w #8,d0
lsr.w #4,d0 ;shift key data into bits 0-3
and.w #%1111,d0 ;mask off unwanted data
or.w d0,d2 ;store in key word

move.w #$ffbf,(a1) ;write mask
move.w (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #3,d3 ;check for fire_c
bne.s no_firec_b ;if set, fire_c is not pressed
bset #5,d1 ;fire_c is pressed, set relevant bit
no_firec_b:
lsr.w #8,d0 ;shift key data into bits 4-7
and.w #%11110000,d0 ;mask off unwanted data
or.w d0,d2 ;store in key word

move.w #$ff7f,(a1) ;write mask
move.w (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #3,d3 ;check for option
bne.s no_option_b ;if set, option is not pressed
bset #12,d2 ;set option bit
no_option_b:
lsr.w #4,d0 ;shift key data into bits 8-11
and.w #%111100000000,d0 ;mask off unwanted bits
or.w d0,d2 ;store key data
move.b d1,jp2_dir ;save directional+fire data in variable
move.w d2,jp2_key ;save key data in variable
rts

jp1_dir: ds.b 1
jp2_dir: ds.b 1
jp1_key: ds.w 1
jp2_key: ds.w 1


txt_table:
dc.l d0_txt,d1_txt,d2_txt,d3_txt,d4_txt,d5_txt,d6_txt,d7_txt
dc.l k0_txt,k1_txt,k2_txt,k3_txt,k4_txt,k5_txt,k6_txt,k7_txt
dc.l k8_txt,k9_txt,k10_txt,k11_txt,k12_txt,k13_txt,0

credits_txt:
dc.b 27,"E"
dc.b "POWERPAD TESTER",13,10
dc.b "===============",13,10,13,10
dc.b "Coded by Mr Pink",13,10,13,10
dc.b "(C) 1995 RESERVOIR GODS",13,10,13,10,13,10
dc.b "Press SPACE to begin testing...",0

pos_cursor_txt dc.b 27,"Y"
cursor_y dc.b 34
cursor_x dc.b 32,0

clr_txt dc.b 27,"E"
* 123456789012345678901234567890123456789
dc.b "POWERPAD A POWERPAD B",0
on_txt dc.b "+",0
space_txt dc.b " ",0

d0_txt dc.b "UP",0
d1_txt dc.b "DOWN",0
d2_txt dc.b "LEFT",0
d3_txt dc.b "RIGHT",0
d4_txt dc.b "",0
d5_txt dc.b "FIRE C",0
d6_txt dc.b "FIRE B",0
d7_txt dc.b "FIRE A",0

k0_txt dc.b "*",0
k1_txt dc.b "7",0
k2_txt dc.b "4",0
k3_txt dc.b "1",0
k4_txt dc.b "0",0
k5_txt dc.b "8",0
k6_txt dc.b "5",0
k7_txt dc.b "2",0
k8_txt dc.b "#",0
k9_txt dc.b "9",0
k10_txt dc.b "6",0
k11_txt dc.b "3",0
k12_txt dc.b "Option",0
k13_txt dc.b "Pause",0

NEWPAD.S

*************************** 
* JAGUAR POWERPAD HANDLER *
** FOR ATARI STE/FALCON ***
**>>>TEST PROGRAM V1.1<<***
**** CODED BY MR. PINK ****
* (C) 1995 RESERVOIR GODS *
***************************

* "1.1" Fix by Eddies' Cat Un-Interactive June 1996*
* (This version should sense all button/pad combinations
* whereas on the original certain combinations caused
* some held switches to cut out.)

; This is a little program to demonstrate the powerpad routines.
; It simply displays which buttons are currently being pressed
; on each powerpad.
; Press SPACE to quit


move.l a7,a5
move.l 4(a5),a5
move.l 12(a5),d0
add.l 20(a5),d0
add.l 28(a5),d0
add.l #$100,d0
move.l d0,-(a7)
move.l a5,-(a7)
move d0,-(a7)
move #$4a,-(a7)
trap #1
add.l #12,a7

clr.w -(a7)
pea $200000 ;supervisor mode
trap #1
bsr print_credits
bsr print_power_info

clr.w -(a7) ;term
trap #1


print_credits
lea credits_txt,a0
bsr print
wsp cmp.b #$39,$fffffc02.w
bne.s wsp
rts

print_power_info
bsr print_intro_txt
wait bsr read_powerpad_a
bsr read_powerpad_b
bsr print_dir_bits
cmp.b #$39,$fffffc02.w
bne.s wait
rts

print_dir_bits
move.b #34,cursor_y
move.b #34+10,cursor_x
move.b jp1_dir,d0
moveq #7,d1
bsr show_bits
move.w jp1_key,d0
move.w #13,d1
bsr show_bits

move.b #34,cursor_y
move.b #34+39,cursor_x
move.b jp2_dir,d0
moveq #7,d1
bsr show_bits
move.w jp2_key,d0
move.w #13,d1

show_bits
lsr.w d0
bcs.s do_on
bsr print_space
bra next_bit
do_on bsr print_on
next_bit
addq.b #1,cursor_y
dbra d1,show_bits
rts

print_intro_txt
lea clr_txt,a0
bsr print
lea txt_table,a6
next_txt
move.l (a6)+,a0
cmpa.w #0,a0
beq last_txt
move.b #32,cursor_x
bsr position_cursor
bsr print
move.b #32+30,cursor_x
bsr position_cursor
bsr print
addq.b #1,cursor_y
bra next_txt
last_txt
rts

print_on
bsr position_cursor
lea on_txt,a0
bra print

print_space
bsr position_cursor
lea space_txt,a0
bra print

position_cursor:
movem.l d0-2/a0-a2,-(a7)
pea pos_cursor_txt
bra.s prnt
print: movem.l d0-2/a0-2,-(a7)
pea (a0)
prnt: move.w #9,-(a7)
trap #1
addq.l #6,a7
movem.l (a7)+,d0-2/a0-2
rts



read_powerpad_a:
lea $ffff9200.w,a0 ;extended port address (read only)
lea 2(a0),a1 ;extended port address (read/write)
moveq #0,d2 ;clear d2 - it will contain key information

move.w #$fffe,(a1) ;write mask
move.b (a1),d0 ;read directional data BYTE
move.w (a0),d3 ;read fire_a/pause data
not.w d0 ;invert bits (0->1)
move.w d0,d1 ;save directional data
lsr.w d3 ;check bit 0 (pause data)
bcs.s no_pause_a ;if set, pause is not pressed
bset #13,d2 ;pause is pressed so set pause bit
no_pause_a:
lsr.w d3 ;check bit 1 (fire a data)
bcs.s no_firea_a ;if set, fire is not pressed
bset #7,d1 ;fire_a is pressed, so set fire_a bit
no_firea_a:
move.w #$fffd,(a1) ;write mask
move.b (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #1,d3 ;check fire_b
bne.s no_fireb_a ;if set, fire_b is not pressed
bset #6,d1 ;fire_b is pressed, set relevant bit
no_fireb_a:
and.w #%1111,d0 ;mask off unwanted data
or.w d0,d2 ;store in key word

move.w #$fffb,(a1) ;write mask
move.b (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #1,d3 ;check for fire_c
bne.s no_firec_a ;if set, fire_c is not pressed
bset #5,d1 ;fire_c is pressed, set relevant bit
no_firec_a:
lsl.w #4,d0 ;shift key data into bits 4-7
and.w #%11110000,d0 ;mask off unwanted data
or.w d0,d2 ;store in key word

move.w #$fff7,(a1) ;write mask
move.b (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #1,d3 ;check for option
bne.s no_option_a ;if set, option is not pressed
bset #12,d2 ;set option bit
no_option_a:
lsl.w #8,d0
and.w #%111100000000,d0 ;mask off unwanted bits
or.w d0,d2 ;store key data
move.b d1,jp1_dir ;save directional+fire data in variable
move.w d2,jp1_key ;save key data in variable
rts



read_powerpad_b:
lea $ffff9200.w,a0 ;extended port address (read only)
lea 2(a0),a1 ;extended port address (read/write)
moveq #0,d2 ;clear d2 - it will contain key information
move.w #$ffef,(a1) ;write mask
move.b (a1),d0 ;read directional data BYTE
move.w (a0),d3 ;read fire_a/pause data
not.w d0 ;invert bits (0->1)
move.w d0,d1 ;save directional data
lsr.w #4,d1 ;shift into low bits (0-3)
and.w #%1111,d1 ;mask off unwanted data
btst #2,d3 ;check bit 2 (pause data)
bne.s no_pause_b ;if set, pause is not pressed
bset #13,d2 ;pause is pressed so set pause bit
no_pause_b:
btst #3,d3 ;check bit 3 (fire a data)
bne.s no_firea_b ;if set, fire is not pressed
bset #7,d1 ;fire_a is pressed, so set fire_a bit
no_firea_b:
move.w #$ffdf,(a1) ;write mask
move.b (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #3,d3 ;check fire_b
bne.s no_fireb_b ;if set, fire_b is not pressed
bset #6,d1 ;fire_b is pressed, set relevant bit
no_fireb_b:
lsr.w #4,d0 ;shift key data into bits 0-3
and.w #%1111,d0 ;mask off unwanted data
or.w d0,d2 ;store in key word

move.w #$ffbf,(a1) ;write mask
move.b (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #3,d3 ;check for fire_c
bne.s no_firec_b ;if set, fire_c is not pressed
bset #5,d1 ;fire_c is pressed, set relevant bit
no_firec_b:
and.w #%11110000,d0 ;mask off unwanted data
or.w d0,d2 ;store in key word

move.w #$ff7f,(a1) ;write mask
move.b (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #3,d3 ;check for option
bne.s no_option_b ;if set, option is not pressed
bset #12,d2 ;set option bit
no_option_b:
lsl.w #4,d0 ;shift key data into bits 8-11
and.w #%111100000000,d0 ;mask off unwanted bits
or.w d0,d2 ;store key data
move.b d1,jp2_dir ;save directional+fire data in variable
move.w d2,jp2_key ;save key data in variable
rts



jp1_dir: ds.b 1
jp2_dir: ds.b 1
jp1_key: ds.w 1
jp2_key: ds.w 1


txt_table:
dc.l d0_txt,d1_txt,d2_txt,d3_txt,d4_txt,d5_txt,d6_txt,d7_txt
dc.l k0_txt,k1_txt,k2_txt,k3_txt,k4_txt,k5_txt,k6_txt,k7_txt
dc.l k8_txt,k9_txt,k10_txt,k11_txt,k12_txt,k13_txt,0

credits_txt:
dc.b 27,"E"
dc.b "POWERPAD TESTER v1.1",13,10
dc.b "====================",13,10,13,10
dc.b "Coded by Mr Pink, fixed by Ed.",13,10,13,10
dc.b "(C) 1995/6 RESERVOIR GODS",13,10,13,10,13,10
dc.b "Press SPACE to begin testing...",0

pos_cursor_txt dc.b 27,"Y"
cursor_y dc.b 34
cursor_x dc.b 32,0

clr_txt dc.b 27,"E"
* 123456789012345678901234567890123456789
dc.b "POWERPAD A POWERPAD B",0
on_txt dc.b "+",0
space_txt dc.b " ",0

d0_txt dc.b "UP",0
d1_txt dc.b "DOWN",0
d2_txt dc.b "LEFT",0
d3_txt dc.b "RIGHT",0
d4_txt dc.b "",0
d5_txt dc.b "FIRE C",0
d6_txt dc.b "FIRE B",0
d7_txt dc.b "FIRE A",0

k0_txt dc.b "*",0
k1_txt dc.b "7",0
k2_txt dc.b "4",0
k3_txt dc.b "1",0
k4_txt dc.b "0",0
k5_txt dc.b "8",0
k6_txt dc.b "5",0
k7_txt dc.b "2",0
k8_txt dc.b "#",0
k9_txt dc.b "9",0
k10_txt dc.b "6",0
k11_txt dc.b "3",0
k12_txt dc.b "Option",0
k13_txt dc.b "Pause",0

PADHANDL.S

******************************* 
* JAGUAR POWERPAD HANDLER V1.1*
**** FOR ATARI STE/FALCON *****
****** CODED BY MR. PINK ******
** (C) 1995/6 RESERVOIR GODS **
*******************************

* "1.1" Fix by Eddies' Cat Un-Interactive June 1996 *
* (Now certain button/pad combinations don't cancel each other out)

; The routines to read powerpads A and B are separate.
; Each updates two variables, a directional byte and a key word.
; The directional byte contains information about the directions being
; pressed and the state of the fire buttons.
; The key word contains info about all the numeric keypad buttons
; and Pause and Option buttons.

; NOTE: You must be in supervisor mode to call these routines!
; You must either call them every vertical blank or put them on the vbl.

; DIRECTIONAL BYTE FORMAT
; -------------------
; Bit | Powerpad key
; ------------------
; 0 | Up
; 1 | Down
; 2 | Left
; 3 | Right
; 4 | (not used)
; 5 | Fire C
; 6 | Fire B
; 7 | Fire A

; KEY WORD FORMAT
; --------------
; Bit | Powerpad Key
; --------------
; 0 | *
; 1 | 7
; 2 | 4
; 3 | 1
; 4 | 0
; 5 | 8
; 6 | 5
; 7 | 2
; 8 | #
; 9 | 9
; 10 | 6
; 11 | 3
; 12 | Option
; 13 | Pause



read_powerpad_a:
lea $ffff9200.w,a0 ;extended port address (read only)
lea 2(a0),a1 ;extended port address (read/write)
moveq #0,d2 ;clear d2 - it will contain key information

move.w #$fffe,(a1) ;write mask
move.b (a1),d0 ;read directional data BYTE
move.w (a0),d3 ;read fire_a/pause data
not.w d0 ;invert bits (0->1)
move.w d0,d1 ;save directional data
lsr.w d3 ;check bit 0 (pause data)
bcs.s no_pause_a ;if set, pause is not pressed
bset #13,d2 ;pause is pressed so set pause bit
no_pause_a:
lsr.w d3 ;check bit 1 (fire a data)
bcs.s no_firea_a ;if set, fire is not pressed
bset #7,d1 ;fire_a is pressed, so set fire_a bit
no_firea_a:
move.w #$fffd,(a1) ;write mask
move.b (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #1,d3 ;check fire_b
bne.s no_fireb_a ;if set, fire_b is not pressed
bset #6,d1 ;fire_b is pressed, set relevant bit
no_fireb_a:
and.w #%1111,d0 ;mask off unwanted data
or.w d0,d2 ;store in key word

move.w #$fffb,(a1) ;write mask
move.b (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #1,d3 ;check for fire_c
bne.s no_firec_a ;if set, fire_c is not pressed
bset #5,d1 ;fire_c is pressed, set relevant bit
no_firec_a:
lsl.w #4,d0 ;shift key data into bits 4-7
and.w #%11110000,d0 ;mask off unwanted data
or.w d0,d2 ;store in key word

move.w #$fff7,(a1) ;write mask
move.b (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #1,d3 ;check for option
bne.s no_option_a ;if set, option is not pressed
bset #12,d2 ;set option bit
no_option_a:
lsl.w #8,d0
and.w #%111100000000,d0 ;mask off unwanted bits
or.w d0,d2 ;store key data
move.b d1,jp1_dir ;save directional+fire data in variable
move.w d2,jp1_key ;save key data in variable
rts



read_powerpad_b:
lea $ffff9200.w,a0 ;extended port address (read only)
lea 2(a0),a1 ;extended port address (read/write)
moveq #0,d2 ;clear d2 - it will contain key information
move.w #$ffef,(a1) ;write mask
move.b (a1),d0 ;read directional data BYTE
move.w (a0),d3 ;read fire_a/pause data
not.w d0 ;invert bits (0->1)
move.w d0,d1 ;save directional data
lsr.w #4,d1 ;shift into low bits (0-3)
and.w #%1111,d1 ;mask off unwanted data
btst #2,d3 ;check bit 2 (pause data)
bne.s no_pause_b ;if set, pause is not pressed
bset #13,d2 ;pause is pressed so set pause bit
no_pause_b:
btst #3,d3 ;check bit 3 (fire a data)
bne.s no_firea_b ;if set, fire is not pressed
bset #7,d1 ;fire_a is pressed, so set fire_a bit
no_firea_b:
move.w #$ffdf,(a1) ;write mask
move.b (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #3,d3 ;check fire_b
bne.s no_fireb_b ;if set, fire_b is not pressed
bset #6,d1 ;fire_b is pressed, set relevant bit
no_fireb_b:
lsr.w #4,d0 ;shift key data into bits 0-3
and.w #%1111,d0 ;mask off unwanted data
or.w d0,d2 ;store in key word

move.w #$ffbf,(a1) ;write mask
move.b (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #3,d3 ;check for fire_c
bne.s no_firec_b ;if set, fire_c is not pressed
bset #5,d1 ;fire_c is pressed, set relevant bit
no_firec_b:
and.w #%11110000,d0 ;mask off unwanted data
or.w d0,d2 ;store in key word

move.w #$ff7f,(a1) ;write mask
move.b (a1),d0 ;read key data
move.w (a0),d3 ;read fire data
not.w d0 ;invert bits (0->1)
btst #3,d3 ;check for option
bne.s no_option_b ;if set, option is not pressed
bset #12,d2 ;set option bit
no_option_b:
lsl.w #4,d0 ;shift key data into bits 8-11
and.w #%111100000000,d0 ;mask off unwanted bits
or.w d0,d2 ;store key data
move.b d1,jp2_dir ;save directional+fire data in variable
move.w d2,jp2_key ;save key data in variable
rts



jp1_dir: ds.b 1
jp2_dir: ds.b 1
jp1_key: ds.w 1
jp2_key: ds.w 1

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT