Gameboy Development Forum

Discussion about software development for the old-school Gameboys, ranging from the "Gray brick" to Gameboy Color
(Launched in 2008)

You are not logged in.

Ads

#1 2014-10-17 10:19:22

Crona
Member
From: Wisconsin
Registered: 2014-09-23
Posts: 58
Website

Super Gameboy Second Controller Input?

I'm trying to make a simple pong game that you can play multiplayer via Super Gameboy kinda like Bomberman GB did. I found the function that checks if your playing on a super gameboy or regular gameboy, but now I just need to figure out the second controllers inputs. Is there any information on that out there?

Offline

 

#2 2014-10-22 07:07:30

Tauwasser
Member
Registered: 2010-10-23
Posts: 160

Re: Super Gameboy Second Controller Input?

Check out the SGB Multiplayer Commands here. You can use BGB to test if you send the packets right. You might want to check out higan to see if you can get two-controller support that way.

cYa,

Tauwasser

Last edited by Tauwasser (2014-10-22 07:08:04)

Offline

 

#3 2014-10-22 10:10:12

Crona
Member
From: Wisconsin
Registered: 2014-09-23
Posts: 58
Website

Re: Super Gameboy Second Controller Input?

Ok I found this within that thing you linked, but I dont really know how to use this. Do you understand it? Can you give me an example of it being used?

SGB Command 11h - MLT_REQ
Used to request multiplayer mode (ie. input from more than one joypad).
Because this function provides feedback from the SGB/SNES to the gameboy program, it is also used to detect SGB hardware.
  Byte  Content
  0     Command*8+Length    (fixed length=1)
  1     Multiplayer Control (0-3) (Bit0=Enable, Bit1=Two/Four Players)
          0 = One player
          1 = Two players
          3 = Four players
  2-F   Not used (zero)
In one player mode, the second joypad (if any) is used for the SGB system program. In two player mode, both joypads are used for the game. Because SNES have only two joypad sockets, four player mode requires an external "Multiplayer 5" adapter.

Reading Multiple Controllers (Joypads)
When having enabled multiple controllers by MLT_REQ, data for each joypad can be read out through JOYPAD register (FF00) as follows: First set P14 and P15 both HIGH (deselect both Buttons and Cursor keys), you can now read the lower 4bits of FF00 which indicate the joypad ID for the following joypad input:
  0Fh  Joypad 1
  0Eh  Joypad 2
  0Dh  Joypad 3
  0Ch  Joypad 4
Next, set P14 and P15 low (one after each other) to select Buttons and Cursor lines, and read-out joypad state as normally. When completed, set P14 and P15 back HIGH, this automatically increments the joypad number (or restarts counting once reached the lastmost joypad). Repeat the procedure until you have read-out states for all two (or four) joypads.






Also I found this in hardware.h, which im 99% sure has to do with this, but I dont know how to use it.

#define P1_REG        (*(__REG)0xFF00)    /* Joystick: 1.1.P15.P14.P13.P12.P11.P10 */

Last edited by Crona (2014-10-22 10:20:08)

Offline

 

#4 2014-10-26 23:36:24

Tauwasser
Member
Registered: 2010-10-23
Posts: 160

Re: Super Gameboy Second Controller Input?

Did you look at the SGB Command Packet Transfers part?

Below is example code from a game:

Code:

;; Point hl to SGB command
;; don't interrupt this sequence,
;; e.g. by reading keypad
ld a, [hl] ;; length field in packet header
@send_sgb:
and a, $07
ret z
ld b, a
@for_length:
push bc
xor a, a
ld [$FF00 + $00], a
ld a, $30
ld [$FF00 + $00], a
ld b, $10 ;; 0x10 bytes per packet
@outer:
ld e, $08 ;; 0x08 bits per byte
ldi a, [hl]
ld d, a
@inner:
bit 0, d  ;; set P14 or P15 according to current data bit to send
ld a, $10
jr nz, @5C38
ld a, $20
@5C38:
ld [$FF00 + $00], a
ld a, $30
ld [$FF00 + $00], a
rr d
dec e
jr nz, @inner
dec b
jr nz, @outer
ld a, $20
ld [$FF00 + $00], a
ld a, $30
ld [$FF00 + $00], a
call delay_loop
pop bc
dec b
jr nz, @for_length
ret

@delay_loop:
ld de, $1B58
@loop:
nop
nop
nop
dec de
ld a, d
or a, e
jr nz, @loop
ret

The initial MLT_REQ check would then look like this:

Code:

@check_sgb
ld hl, @MLT_REQ_ON
call @send_sgb
call @delay_loop
ld a, [$FF00 + $00] ;; read joypad ID
and a, $03
cp a, $03
jr nz, @is_sgb ;; should not be joypad 1
;; simulate reading joypad state
;; to get SGB to apply MLT_REQ
ld a, $20      ;; P14 low
ld [$FF00 + $00], a
ld a, [$FF00 + $00]
ld a, [$FF00 + $00]
call @delay_loop
call @delay_loop
ld a, $30      ;; P14, P15 low
ld [$FF00 + $00], a
call @delay_loop
call @delay_loop
ld a, $10      ;; P15 low
ld [$FF00 + $00], a
ld a, [$FF00 + $00]
ld a, [$FF00 + $00]
ld a, [$FF00 + $00]
ld a, [$FF00 + $00]
ld a, [$FF00 + $00]
ld a, [$FF00 + $00]
call @delay_loop
call @delay_loop
ld a, $30      ;; P14, P15 low
ld [$FF00 + $00], a
ld a, [$FF00 + $00]
ld a, [$FF00 + $00]
ld a, [$FF00 + $00]
call @delay_loop
call @delay_loop
ld a, [$FF00 + $00] ;; read joypad ID
and a, $03
cp a, $03
jr nz, @is_sgb ;; should not be 1
call @send_mlt_req_off
and a, a
ret
@is_sgb:
call @send_mlt_req_off
scf
ret

@send_mlt_req_off:
ld hl, @MLT_REQ_OFF
call @send_sgb
jp @delay_loop
@MLT_REQ_OFF:
db $89, $00, $00, $00, $00, $00, $00, $00
db $00, $00, $00, $00, $00, $00, $00, $00
@MLT_REQ_ON:
db $89, $01, $00, $00, $00, $00, $00, $00
db $00, $00, $00, $00, $00, $00, $00, $00

And that would be my short analysis of SGB transfers. I guess you'll have to check out if that works for you or not. I'm pretty sure the bulk of the code here is just to make sure the SGB actually updated the controller requests. So if you read all ones after selecting the controller twice, that's bad.

cYa,

Tauwasser

Offline

 

#5 2014-10-27 10:57:07

Crona
Member
From: Wisconsin
Registered: 2014-09-23
Posts: 58
Website

Re: Super Gameboy Second Controller Input?

Is it possible to do that in C? I have yet to learn asm.

Offline

 

#6 2016-03-16 20:16:34

rychan
Member
From: Paignton, Devon, UK
Registered: 2015-12-16
Posts: 103
Website

Re: Super Gameboy Second Controller Input?

Yes!, Found this post, and whilst I don't fully understand all the ASM involved I'm going to try to! I think there's a way to make it less ASM involved perhaps with GBDK as you're essentially timing writes to a memory address (0xFF00) with pulses of data every 15us , which last for 5 us.

Sooo If you were to create a delay_loop function or two in ASM (one for 15us and another for 5 us) orr possibly just the 5us one and run it 3 times even.

Then Push the correct value of one of the following values into the address, e.g.:

RESET = Binary 00000000  or Decimal 0;
Bit 0 = Binary 00010000 or Decimal 16
Bit 1 = Binary 00100000 or Decimal 32
HIGH = Binary 00110000 or Decimal 48

http://bgb.bircd.org/pandocs.htm#joypadinput  (scroll down to the transferring bits section below it also)

Offline

 

Board footer

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson