Seite anzeigenÄltere VersionenLinks hierherNach oben Diese Seite ist nicht editierbar. Sie können den Quelltext sehen, jedoch nicht verändern. Kontaktieren Sie den Administrator, wenn Sie glauben, dass hier ein Fehler vorliegt. ====== SuperPad64 ====== You can buy a complete adapter including housing here: [[https://www.polyplay.xyz/SuperPad64-8-Player-Interface-Commodore-64|poly.play webshop]] ===== Credits ===== * **Idea and Concept:** Wolfram Sang * **Hardware Design:** Oliver Tscherwitschke * **Software:** Steffen Görzig, Oliver Tscherwitschke ---- ===== Supported Games ===== * RACE+ * Space Moguls * and more ---- ===== Hardware ===== The SuperPad64 is an adapter for the C64 userport and enables you to connect up to eight SNES game pads. {{:superpad64:superpad64_00.jpg?400|}} The complete hardware design of SuperPad64 can be {{ :superpad64:superpad64.zip |downloaded here}}. This includes the schematics and layout in Eagle and PDF format, Gerber PCB data and the bill of material and should be everything that is needed to build yourself a SuperPad64. [[:superpad64:Building instructions]]\\ [[:superpad64:Building instructions|Bauanleitung]] ---- ===== Software ===== ==== Implementation in assembler ==== ==== initAndDetectSnes ==== First of all, the adapter has to be initialized and detected: <code> ;; initAndDetectSnes: call this routine first one time to detect and initialize the adapter ;; snesDetectionResult: result of the detection. Encoding: ;; 0: no adapter ;; 1: SuperPad64 snesDetectionResult !byte $00 initAndDetectSnes: lda #$00 ; PB = input sta $dd03 lda $dd02 ora #$04 sta $dd02 ; PA2 = output for latch signal lda $dd00 ora #$04 ; PA2 = high sta $dd00 and #$fb ; PA2 = high sta $dd00 ldx #$0f initAndDetectSnesLoop: lda $dd01 ; read 16 bytes dex bpl initAndDetectSnesLoop cmp $dd01 ; byte 16==byte 17? beq initAndDetectSnesDone ; yes inc snesDetectionResult ; adapter detected with at least one pad plugged in initAndDetectSnesDone: rts </code> After the initialization the input can be read from the pads. The following routines differ between the number of pads and also the number of input buttons. For example "4Pads5Bits" indicates that the input form the first 4 Pads is read and 5 bits (directions and fire button "B") analog to a standard joystick input. "8Pads12Bits" reads from 8 Pads 12 bits (directions and all buttons). The resulting bit logic is negated, e.g. when a button or a direction is pressed, the according bit is 0 (and not 1). === 8Pads12Bits === This is the universal read function to read a given number of bits from all eight gamepads. <code> tmp = $02 ; temp variable in zero page ; 'pads' stores the button state of all gamepads. pads !word 0,0,0,0,0,0,0,0 ; CIA Register definitions CIA2_PRA = $DD00 CIA2_PRB = $DD01 CIA2_DDRA = $DD02 CIA2_DDRB = $DD03 ; =========================================== ; =========== Read all 8 gamepads =========== ; Input: A: Number of bits to read from gamepad ; Output: Array 'pads' (8 x 16-bits): Button states (low-active) ; Uses zero page variable 'tmp' ; getSnes8PadsNBits sta tmp ; bit counter ; Generate latch pulse to store button data lda CIA2_PRA ora #$04 sta CIA2_PRA ; Latch = 1 and #$FB sta CIA2_PRA ; Latch = 0 sp64_bitloop lda CIA2_PRB ; Read data from Port B... ldx #0 sp64_padloop ; ... and shift it in array 'pads' lsr ; rol pads,x ; bits: Up Down Left Right A X L R rol pads+1,x ; bits: x x x x B Y Select Start inx inx cpx #16 bmi sp64_padloop dec tmp bne sp64_bitloop rts </code> To read all 12 buttons just call this routine with A set to 12: <code> lda #12 jsr getSnes8PadsNBits </code> Now 'pads' contains the button states of each gamepad in the lower 12 bits.\\ Please note that the bits are low-active, i.e. the bit is '0' if the button is pressed and '1' if not. ^ Bit ^ 15 ^ 14 ^ 13 ^ 12 ^ 11 ^ 10 ^ 9 ^ 8 ^ 7 ^ 6 ^ 5 ^ 4 ^ 3 ^ 2 ^ 1 ^ 0 ^ | Button | x | x | x | x | B | Y | Select | Start | Up | Down | Left | Right | A | X | L | R | === 8Pads8Bits === == Variant A == If 8 buttons are enough for your application, just set A to 8 and call the above function. In this case only the lower bytes of the pads array members are relevant\\ You could save 8 bytes of RAM if you change the 'pads' array to !byte type and commenting out the 'rol pads+1,x' line. <code> lda #8 jsr getSnes8PadsNBits </code> ^ Bit ^ 7 ^ 6 ^ 5 ^ 4 ^ 3 ^ 2 ^ 1 ^ 0 ^ | Button | B | Y | Select | Start | Up | Down | Left | Right | == Variant B == If you prefer the bits to be in the same order as a joystick in one of the control ports would deliver, you can use this special function: <code> tmp = $02 ; temp variable in zero page ; 'pads' stores the button state of all gamepads. pads !byte 0,0,0,0,0,0,0,0 ; CIA Register definitions CIA2_PRA = $DD00 CIA2_PRB = $DD01 CIA2_DDRA = $DD02 CIA2_DDRB = $DD03 ; =========================================== ; =========== Read all 8 gamepads =========== ; Input: None ; Output: Array 'pads' (8 x 8-bits): Button states (low-active) ; Uses zero page variable 'tmp' ; getSnes8Pads8Bits lda #8 sta tmp ; bit counter ; Generate latch pulse to store button data lda CIA2_PRA ora #$04 sta CIA2_PRA ; Latch = 1 and #$FB sta CIA2_PRA ; Latch = 0 sp64_8x8_bitloop lda CIA2_PRB ; Read data from Port B... ldx #0 sp64_8x8_padloop ; ... and shift it in array 'pads' lsr ; ror pads,x ; bits: Right Left Down Up Start Select Y B inx cpx #8 bmi sp64_8x8_padloop dec tmp bne sp64_8x8_bitloop ; Make bit order compatible to control port ; Bits: Start Select Y B Right Left Down Up ldx #0 sp64_8x8_fixloop lda pads,x ror ror pads,x ror ror pads,x ror ror pads,x ror ror pads,x inx cpx #8 bmi sp64_8x8_fixloop rts </code> ^ Bit ^ 7 ^ 6 ^ 5 ^ 4 ^ 3 ^ 2 ^ 1 ^ 0 ^ | Button | Start | Select | Y | B (Fire) | Right | Left | Down | Up | === 8Pads5Bits === <code> ;;;;;;;;;;;;;;;; ;; 8Pads5Bits ;; ;;;;;;;;;;;;;;;; result8Pads5Bits !byte $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff getSnes8Pads5Bits: lda $dd00 ora #$04 ; PA2 = high sta $dd00 and #$fb ; PA2 = low sta $dd00 lda $dd01 ; get values for firebutton "B" pha ; remember firebutton values in heap lda $dd01 ; get and forget values for "Y" lda $dd01 ; get and forget values for "SELECT" lda $dd01 ; get and forget values for "START" ldy #$03 ; get 4 directions getSnes8Pads5BitsNextDirection: lda $dd01 ; get direction values "up", "down", "left", and "right" ldx #$07 ; store direction in joystick variables getSnes8Pads5BitsLoop: rol ; shift bit left into carry... ror result8Pads5Bits,x ; ...then into its destination dex bpl getSnes8Pads5BitsLoop dey bpl getSnes8Pads5BitsNextDirection ; now values in each joy: right, left, down, up, x, x, x, x pla ; restore firebutton values from heap to accu ldx #$07 ; add firebutton and generate encoding compatible to ; standard joystick format: ; 0,0,0, fire, right, left, down, up getSnes8Pads5BitsConvertToStandardLoop: rol ; shift fire bit to carry ... ror result8Pads5Bits,x ; ...then into its destination lsr result8Pads5Bits,x ; fill left three bits with 0 lsr result8Pads5Bits,x lsr result8Pads5Bits,x dex bpl getSnes8Pads5BitsConvertToStandardLoop rts </code> ^ Bit ^ 7 ^ 6 ^ 5 ^ 4 ^ 3 ^ 2 ^ 1 ^ 0 ^ | Button | 0 | 0 | 0 | B (Fire) | Right | Left | Down | Up | === 4Pads8Bits === <code> ;;;;;;;;;;;;;;;; ;; 4Pads8Bits ;; ;;;;;;;;;;;;;;;; result4Pads8Bits !byte $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff tmp4Pds8Bits !byte $00 getSnes4Pads8Bits: lda $dd00 ora #$04 ; PA2 = high sta $dd00 and #$fb ; PA2 = low sta $dd00 lda #$07 sta tmp4Pds8Bits ; bit counter 7..0 getSnes4Pads8BitsBitLoop: lda $dd01 ; read data from port b ldx #$00 getSnes4Pads8BitsPadLoop: ; move data into result array lsr ror result4Pads8Bits,x ; bits: right left down up START SELECT Y fire(B) inx cpx #$04 ; stop after 4 Pads bmi getSnes4Pads8BitsPadLoop dec tmp4Pds8Bits bpl getSnes4Pads8BitsBitLoop ldx #$00 ; bring bits to standard joystick format: ; START, SELECT, Y, fire(B), right, left, down, up getSnes4Pads8BitsStandardLoop: lda result4Pads8Bits,x ror ror result4Pads8Bits,x ror ror result4Pads8Bits,x ror ror result4Pads8Bits,x ror ror result4Pads8Bits,x inx cpx #$04 bmi getSnes4Pads8BitsStandardLoop rts </code> ^ Bit ^ 7 ^ 6 ^ 5 ^ 4 ^ 3 ^ 2 ^ 1 ^ 0 ^ | Button | Start | Select | Y | B (Fire) | Right | Left | Down | Up | === 4Pads5Bits === <code> ;;;;;;;;;;;;;;;; ;; 4Pads5Bits ;; ;;;;;;;;;;;;;;;; result4Pads5Bits !byte $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff getSnes4Pads5Bits: lda $dd00 ora #$04 ; PA2 = high sta $dd00 and #$fb ; PA2 = low sta $dd00 lda $dd01 ; get values for firebutton "B" pha ; remember firebutton values in heap lda $dd01 ; get and forget values for "Y" lda $dd01 ; get and forget values for "SELECT" lda $dd01 ; get and forget values for "START" ldy #$03 ; get 4 directions getSnes4Pads5BitsNextDirection: lda $dd01 ; get direction values "up", "down", "left", and "right" ldx #$00 ; store direction in joystick variables getSnes4Pads5BitsShiftBits: lsr ; shift bit left into carry... ror result4Pads5Bits,x ; ...then into its destination inx cpx #$04 ; stop after 4 pads bmi getSnes4Pads5BitsShiftBits dey bpl getSnes4Pads5BitsNextDirection ; now values in each joy: right, left, down, up, x, x, x, x pla ; restore firebutton values from heap to accu ldx #$00 ; add firebutton and generate encoding compatible to ; standard joystick format: ; 0,0,0, fire, right, left, down, up getSnes4Pads5BitsFixLoop: lsr ; shift fire bit to carry ... ror result4Pads5Bits,x ; ...then into its destination lsr result4Pads5Bits,x ; fill left three bits with 0 lsr result4Pads5Bits,x lsr result4Pads5Bits,x inx cpx #$04 ; stop after 4 pads bmi getSnes4Pads5BitsFixLoop rts </code> ^ Bit ^ 7 ^ 6 ^ 5 ^ 4 ^ 3 ^ 2 ^ 1 ^ 0 ^ | Button | 0 | 0 | 0 | B (Fire) | Right | Left | Down | Up | ==== Test Program ==== A SuperPad64 test program can be {{ :superpad64:superpad64-test.zip |downloaded here}}. superpad64.txt Zuletzt geändert: 2020/10/12 13:33von polyplay