Giter Club home page Giter Club logo

Comments (59)

siriokds avatar siriokds commented on July 28, 2024 1

from devkitsms.

sverx avatar sverx commented on July 28, 2024

Sure! Send them over! ❤️

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

Sure! Send them over! ❤️

How can I send you my mods?

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024
  1. This is the mandatory mod to let cart runs correctly even on SC-3000 (only joypad supported)

ctr0_sg.s :

From line 45:

.org 0x66 ; handle NMI
jp _SG_nmi_isr

psgini_tab:
db 0x9F, 0xBF, 0xDF, 0xFF

.org 0x70
init:
ld sp,#0xc3f0 ; set stack pointer at end of RAM

; Initialize PSG as soon as possible!
ld hl,psgini_tab
ld bc,#0x047f
otir

; Init PPI on SC (no effect on SG)
ld a, #0x9F
out (0xDF),a ; Config PPI (no effect on SG-1000)
ld a, #7
out (0xDE),a ; Select ROW 7 (row 7 of PPI is joypad = default - no effect on SG-1000)

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

This is the detection of PPI, in order to use the keyboard on SC-3000. I use this instead the init PPI of the previous message. You can save a byte containing if keyboard is present or not.

SC_PPI_C: equ 0xDE
SC_PPI_CTRL: equ 0xDF

;---------------------------------------
ppi_init:
;---------------------------------------
ld a, $92 ; Init PPI (if present). PortC = Ouput, PortA + PortB = Input
out (SC_PPI_CTRL),a
call ppi_pause

			xor		a
			ld		(KBD_PRESENT),a			; default value, 0 = keyboard absent

			ld		a,$55
			call	ppi_test
			ld		c, a
			ld		a,$AA
			call	ppi_test

			or		c							; merge the two attempts
			cpl									; invert it
			and		1
			ld		(KBD_PRESENT),a				; save it, 0x01 = keyboard present, 0x00 keyboard absent (SG-1000)

			ld		a, 7						; Set row 7 (joypad) as default
			out		(SC_PPI_C), a
			ret

; b = test value
;---------------------------------------
ppi_test:
;---------------------------------------
ld b, a
out (SC_PPI_C),a
call ppi_pause
in a,(SC_PPI_C)
cp b
ld a, $00 ; "xor a" cannot be used. Zero Flag must be intact.
jr z, ppi_test_noerr
dec a ; c = 0xFF if not detected
ppi_test_noerr:
ret

ppi_pause:
nop
nop
ret

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

This is the way i read JOYSTICK/KEYBOARD of Player 1 with standard Sega mapping:

; Call this to obtain joystick + keyboard keys info merged.
;
; OUTPUT:
; A = joy/key bits (1 = pressed, 0 = not pressed)
;
; format bits: 5 | 4 | 3 | 2 | 1 | 0
; TrigR | TrigL | Right | Left | Down | Up |
;----------------------------------------------------------------
;================================================================
SC3K_InputRead:
;================================================================
;----------------------------------------------------------------
call KeybJoyRead
cpl
and 3Fh
ret

;---------------------------------------------------------------
PpiRowRead:
;---------------------------------------------------------------
ld a, b
out (SC_PPI_C), a ; no effect on SG-1000
;===============================================================
JoyRead:
;===============================================================
in a, (SC_PPI_A)
dec b
ret

; Destroy registers: BC
; OUTPUT: A
;===============================================================
KeybJoyRead:
;===============================================================
ld a, (KBD_PRESENT)
or a
jr z, JoyRead

; --- ROW 7 --------------------------------------------
ld b, 7 ; READ JOYSTICK ROW
call PpiRowRead
ld c, a

; --- ROW 6 --------------------------------------------
call PpiRowRead
bit 5,a
jr nz, .noKeyRIGHT:
res 3, c ; CURSOR RIGHT => Joy Right
.noKeyRIGHT:
bit 6,a
jr nz, .noKeyUP:
res 0, c ; CURSOR UP => Joy Up
.noKeyUP:
in a, (SC_PPI_B)
bit 1,a ; Graph
jr nz,.noKeyGraph:
res 4, c ; Left Trigger
.noKeyGraph:

; --- ROW 5 --------------------------------------------
call PpiRowRead
bit 5,a
jr nz, .noKeyLEFT:
res 2, c ; CURSOR LEFT => Joy Left
.noKeyLEFT:

; --- ROW 4 --------------------------------------------
call PpiRowRead
bit 5,a
jr nz, .noKeyDOWN:
res 1, c ; CURSOR DOWN => Joy Down
.noKeyDOWN:

; --- ROW 3 --------------------------------------------
call PpiRowRead
bit 4,a ; InsDel
jr nz,.noKeyInsDel:
res 5, c ; Right Trigger
.noKeyInsDel:

; --- ROW 2 --------------------------------------------
call PpiRowRead
bit 4,a ; Home
jr nz,.noKeyHome:
res 4, c ; Left Trigger
.noKeyHome:

; --- ROW 1 --------------------------------------------
dec b

; --- ROW 0 --------------------------------------------
call PpiRowRead
bit 4,a ; Eng Dier's
jr nz,.noKeyEngDiers:
res 5, c ; Right Trigger
.noKeyEngDiers:
ld a, c

.keybExit:
cpl
ret

from devkitsms.

sverx avatar sverx commented on July 28, 2024

I'm in no way expert on either SG-1000 or SC-3000 so in order to support the SC-3000 I first have to understand if I can just add features to SGlib or if we have to fork some new lib, SClib, for that. Also, the same applies to the crt0.

First of all, I seem to understand the amount of RAM is not the same in them. If so, we probably need to have a specialized crt0, by forking the SG one.

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

I'm in no way expert on either SG-1000 or SC-3000 so in order to support the SC-3000 I first have to understand if I can just add features to SGlib or if we have to fork some new lib, SClib, for that. Also, the same applies to the crt0.

First of all, I seem to understand the amount of RAM is not the same in them. If so, we probably need to have a specialized crt0, by forking the SG one.

I have both physical machines so I can help you to test it. These routines are present (kinda) in every SG-1000 game in order to make games working on both machines (if you look at the cartridge box you can see "Game Cartridge for SG-1000 or SC-3000" message. (check it out https://www.tradergames.fr/15192-large_default/congo-bongo-g-1007-big-box-sg-1000-sc-3000-ntsc-jpn-sans-notice.jpg)

The different crt0 can be useful only for more memory or tape configuration.

The first patch to apply is the following on crt0_sg.sm it's mandatory to run game on both machines using only joypad:

; *** Init PPI on SC (no effect on SG) ***
ld a, #0x9F ; Config PPI (no effect on SG-1000)
out (0xDF),a
ld a, #7 ; Select ROW 7 (row 7 of PPI is joypad = default - no effect on SG-1000)
out (0xDE),a

from devkitsms.

sverx avatar sverx commented on July 28, 2024

The first patch to apply is the following on crt0_sg.sm it's mandatory to run game on both machines using only joypad:

; *** Init PPI on SC (no effect on SG) *** ld a, #0x9F ; Config PPI (no effect on SG-1000) out (0xDF),a ld a, #7 ; Select ROW 7 (row 7 of PPI is joypad = default - no effect on SG-1000) out (0xDE),a

You mean this is needed for any SG-1000 game to make sure they also run on SC-3000? Good to know!

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

The first patch to apply is the following on crt0_sg.sm it's mandatory to run game on both machines using only joypad:
; *** Init PPI on SC (no effect on SG) *** ld a, #0x9F ; Config PPI (no effect on SG-1000) out (0xDF),a ld a, #7 ; Select ROW 7 (row 7 of PPI is joypad = default - no effect on SG-1000) out (0xDE),a

You mean this is needed for any SG-1000 game to make sure they also run on SC-3000? Good to know!

Exactly.

from devkitsms.

sverx avatar sverx commented on July 28, 2024

cf35965

Done.

What's next?

from devkitsms.

sverx avatar sverx commented on July 28, 2024

This is the detection of PPI, in order to use the keyboard on SC-3000. I use this instead the init PPI of the previous message. [...]

So, this code tests if there's a keyboard attached or not?
I suspect it should always be so on the SC-3000 but I guess on a SG-1000 it could detect if a SK-1100 is attached or not, correct?

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

cf35965

Done.

What's next?

Cool.

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

This is the detection of PPI, in order to use the keyboard on SC-3000. I use this instead the init PPI of the previous message. [...]

So, this code tests if there's a keyboard attached or not? I suspect it should always be so on the SC-3000 but I guess on a SG-1000 it could detect if a SK-1100 is attached or not, correct?

Yes. It detect the presence of PPI (8255) chip for keyboard, tape, etc. - Even SK-1100 keyboard for SG-1000 is detected.
Not every emulator can behave correctly on this routine (probably MEKA works). I can test it for you on real SG-1000.

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

This is the detection of PPI, in order to use the keyboard on SC-3000. I use this instead the init PPI of the previous message. [...]

So, this code tests if there's a keyboard attached or not? I suspect it should always be so on the SC-3000 but I guess on a SG-1000 it could detect if a SK-1100 is attached or not, correct?

Yes. It detect the presence of PPI (8255) chip for keyboard, tape, etc. - Even SK-1100 keyboard for SG-1000 is detected. Not every emulator can behave correctly on this routine (probably MEKA works). I can test it for you on real SG-1000.

Detection is simple. PPI sports some latch so, if you write some value, you can expect to read it. Without PPI, you read $FF everytime.

from devkitsms.

sverx avatar sverx commented on July 28, 2024

Detection is simple. PPI sports some latch so, if you write some value, you can expect to read it. Without PPI, you read $FF everytime.

I see some delay is required? Because I could turn that asm code into a few simple lines of C code but I need to make sure it doesn't break any timing requirements...

Do you have the details on timing requirements?

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

from devkitsms.

sverx avatar sverx commented on July 28, 2024

No delay is required. This code is a refactoring version of the official Sega detection routine.

So the official SEGA detection routine had delays? 🤔

If no delays are required, this should work:

__sfr __at 0xDE SC_PPI_C;
__sfr __at 0xDF SC_PPI_CTRL;

#define PPI_TEST_VALUE_1   0x55
#define PPI_TEST_VALUE_2   0xAA

_Bool SG_detectKeyboard (void) {
  bool kbd_detected=false;

  SC_PPI_CTRL=0x92;              // Init PPI (if present). PortC = Ouput, PortA + PortB = Input
  SC_PPI_C=PPI_TEST_VALUE_1;     // write test value 1
  if (SC_PPI_C==PPI_TEST_VALUE_1) {
    SC_PPI_C=PPI_TEST_VALUE_2;   // write test value 2
    if (SC_PPI_C==PPI_TEST_VALUE_2) {
      kbd_detected=true;
    }
  }

  SC_PPI_C=0x07;                 // Set row 7 (joypad) as default
  return (kbd_detected);
}

but note that this doesn't really introduce any delay between writing and reading the SC_PPI_C port, as the generated code shows:

;SGlib.c:365: SC_PPI_C=PPI_TEST_VALUE_1;     // write test value 1
	ld	a, #0x55
	out	(_SC_PPI_C), a
;SGlib.c:366: if (SC_PPI_C==PPI_TEST_VALUE_1) {
	in	a, (_SC_PPI_C)
	sub	a, #0x55
	jr	NZ, 00104$
;SGlib.c:367: SC_PPI_C=PPI_TEST_VALUE_2;   // write test value 2
	ld	a, #0xaa
	out	(_SC_PPI_C), a
;SGlib.c:368: if (SC_PPI_C==PPI_TEST_VALUE_2) {
	in	a, (_SC_PPI_C)
	sub	a, #0xaa
	jr	NZ, 00104$

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

from devkitsms.

sverx avatar sverx commented on July 28, 2024

No delay. Your code should works but I need to see the generated assembly obviously.

Here's the whole generated code, which seems totally fine to me.

_SG_detectKeyboard::
;SGlib.c:362: bool kbd_detected=false;
	ld	c, #0x00
;SGlib.c:364: SC_PPI_CTRL=0x92;              // Init PPI (if present). PortC = Ouput, PortA + PortB = Input
	ld	a, #0x92
	out	(_SC_PPI_CTRL), a
;SGlib.c:365: SC_PPI_C=PPI_TEST_VALUE_1;     // write test value 1
	ld	a, #0x55
	out	(_SC_PPI_C), a
;SGlib.c:366: if (SC_PPI_C==PPI_TEST_VALUE_1) {
	in	a, (_SC_PPI_C)
	sub	a, #0x55
	jr	NZ, 00104$
;SGlib.c:367: SC_PPI_C=PPI_TEST_VALUE_2;   // write test value 2
	ld	a, #0xaa
	out	(_SC_PPI_C), a
;SGlib.c:368: if (SC_PPI_C==PPI_TEST_VALUE_2) {
	in	a, (_SC_PPI_C)
	sub	a, #0xaa
	jr	NZ, 00104$
;SGlib.c:369: kbd_detected=true;
	ld	c, #0x01
00104$:
;SGlib.c:373: SC_PPI_C=0x07;                 // Set row 7 (joypad) as default
	ld	a, #0x07
	out	(_SC_PPI_C), a
;SGlib.c:374: return (kbd_detected);
	ld	a, c
;SGlib.c:375: }
	ret

Usually I insert this routines in CRT0 because are working for SG as well SC.

Well, we could do that too! It's still unclear to me what comes next so let's see and decide later what's more appropriate 😃

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

No delay. Your code should works but I need to see the generated assembly obviously.

Here's the whole generated code, which seems totally fine to me.

_SG_detectKeyboard::
;SGlib.c:362: bool kbd_detected=false;
	ld	c, #0x00
;SGlib.c:364: SC_PPI_CTRL=0x92;              // Init PPI (if present). PortC = Ouput, PortA + PortB = Input
	ld	a, #0x92
	out	(_SC_PPI_CTRL), a
;SGlib.c:365: SC_PPI_C=PPI_TEST_VALUE_1;     // write test value 1
	ld	a, #0x55
	out	(_SC_PPI_C), a
;SGlib.c:366: if (SC_PPI_C==PPI_TEST_VALUE_1) {
	in	a, (_SC_PPI_C)
	sub	a, #0x55
	jr	NZ, 00104$
;SGlib.c:367: SC_PPI_C=PPI_TEST_VALUE_2;   // write test value 2
	ld	a, #0xaa
	out	(_SC_PPI_C), a
;SGlib.c:368: if (SC_PPI_C==PPI_TEST_VALUE_2) {
	in	a, (_SC_PPI_C)
	sub	a, #0xaa
	jr	NZ, 00104$
;SGlib.c:369: kbd_detected=true;
	ld	c, #0x01
00104$:
;SGlib.c:373: SC_PPI_C=0x07;                 // Set row 7 (joypad) as default
	ld	a, #0x07
	out	(_SC_PPI_C), a
;SGlib.c:374: return (kbd_detected);
	ld	a, c
;SGlib.c:375: }
	ret

Usually I insert this routines in CRT0 because are working for SG as well SC.

Well, we could do that too! It's still unclear to me what comes next so let's see and decide later what's more appropriate 😃

Nice!

The next step is to integrate the "readjoy" routine.

This routine check if kbd_detected is set:

  1. If it's set, the routine read the joypad data (player 1) and merge the keyboard data, so what you read is the same byte.
  2. If it isn't set, the routine read the joypad data (player 1) and exit to caller.

The ASM routine I sent you do this. Start with the joypad value (reversed bit: 0 = pressed, 1 = unpressed). If keyboard is available checl for keyboard cursor + 2 keyboard button which act as file 1 and 2 and, through the bit/clr instruction, clear the relative bits. Example: if you press the joypad UP button you will receive $FE (1111 1110) and if you press ALSO the keyboard cursor UP (which clear the bit 0), the value remain $FE. As I remember correctly at the end of routine I execute a CPL instruction to invert the value bits to have a positive pressed bits (1 = pressed, 0 = unpressed).

The bit configuration of the result is the following:

7 6 5 4 3 2 1 0
x x FIRE2 FIRE1 RIGHT LEFT DOWN UP

from devkitsms.

sverx avatar sverx commented on July 28, 2024

I'm not sure it's a good idea to merge the keyboard data with the joypad data... 🤔

Since we already can read joypad data, can't we just add a separate function to read keyboard data?

Of course the programmer can decide to merge the results from the two sources if he wants to, but I see the case when you might want to use both the joypad and the keyboard at the same time but not as the same input...

What's your use case scenario?

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

from devkitsms.

sverx avatar sverx commented on July 28, 2024

Yes, I think we should keep the two parts separated. SGlib already has its functions to access joypad(s) status:

/* functions to read joypad(s) */
unsigned int SG_getKeysStatus (void);
unsigned int SG_getKeysPressed (void);
unsigned int SG_getKeysHeld (void);
unsigned int SG_getKeysReleased (void);

Now, looking at your code it looks like you can tell the status of the keyboard keys by accessing each row.
Do you think we could code something like bool SG_getKBDStatus (unsigned char key) to query the status of any key?
Or maybe it's better to just query a whole row at once with something like unsigned char SG_getKBDStatus (unsigned char row) and have masks to compare bits on the returned value?

Or maybe we could just have a simple function to just read the arrow and trigger keys all in once, similar to what you do already?

Let me know what's your idea 👋

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

Yes, I think we should keep the two parts separated. SGlib already has its functions to access joypad(s) status:

/* functions to read joypad(s) */
unsigned int SG_getKeysStatus (void);
unsigned int SG_getKeysPressed (void);
unsigned int SG_getKeysHeld (void);
unsigned int SG_getKeysReleased (void);

Now, looking at your code it looks like you can tell the status of the keyboard keys by accessing each row. Do you think we could code something like bool SG_getKBDStatus (unsigned char key) to query the status of any key? Or maybe it's better to just query a whole row at once with something like unsigned char SG_getKBDStatus (unsigned char row) and have masks to compare bits on the returned value?

Or maybe we could just have a simple function to just read the arrow and trigger keys all in once, similar to what you do already?

Let me know what's your idea 👋

If we are talking about games, you know where are your keys in key matrix. If you see my routines I read many rows (not every) because they cover my keys requirements.

However You can try to use a keyboard row cache (updated every 3 interrupt) to be sure that you don't read the same row for two different keys which share the same row... SC uses 2 bytes for every row (depending on the keys) to cover the 64 keys requirements. E.g. on Row 0 (zero) you can read PortA and PortB to read your keys.

My routine cover only the standard Arrows+HOME/INS which simulate the joypad following the Sega standards.

If you want to use the SC keyboard in more advanced way I did a CP/M OS for SC years ago:

https://github.com/siriokds/SC-3000-CPM-2.2/blob/main/src/bios/sc3k_bios_kbd.HAL.inc

from devkitsms.

sverx avatar sverx commented on July 28, 2024

I see what you mean! Well, I'd say I want definitely start with something simple, so I will read those arrows+home+ins as a joypad simulation, and we could then expand to the whole keyboard if needs arises.

I'll code something and let's see how it works, then we will proceed from there.

Laters! 👋

from devkitsms.

sverx avatar sverx commented on July 28, 2024

Are there two different keyboard keys that gets mapped to the right trigger? 🤔

edit: ... and also two for left trigger? Should I consider both?

from devkitsms.

sverx avatar sverx commented on July 28, 2024

OK I think this should be correct:

unsigned char SG_readKeyboardJoypad (void) {
  unsigned char joypad=0;       // all keys not pressed unless some detection happens

  SC_PPI_C=0x06;                // we'll read row 6
  unsigned char tmp=SC_PPI_A;   // read kbd data
  if (!(tmp & 0x20))            // check bit 5 (right arrow key)
    joypad|=PORT_A_KEY_RIGHT;
  if (!(tmp & 0x40))            // check bit 6 (up arrow key)
    joypad|=PORT_A_KEY_UP;

  if (!(SC_PPI_B & 0x02))       // read kbd data (on PPI_B) and check bit 1 (Graph key)
    joypad|=PORT_A_KEY_1;

  SC_PPI_C=0x05;                // we'll read row 5
  if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (left arrow key)
    joypad|=PORT_A_KEY_LEFT;

  SC_PPI_C=0x04;                // we'll read row 4
  if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (down arrow key)
    joypad|=PORT_A_KEY_DOWN;

  SC_PPI_C=0x03;                // we'll read row 3
  if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Ins/Del key)
    joypad|=PORT_A_KEY_2;

  SC_PPI_C=0x02;                // we'll read row 2
  if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Home/Clr key)
    joypad|=PORT_A_KEY_1;

  SC_PPI_C=0x00;                // we'll read row 0
  if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Eng Dier's key)
    joypad|=PORT_A_KEY_2;

  SC_PPI_C=0x07;                // set row 7 (joypad) as default
  return joypad;
}

which turns into:

;SGlib.c:381: unsigned char SG_readKeyboardJoypad (void) {
;	---------------------------------
; Function SG_readKeyboardJoypad
; ---------------------------------
_SG_readKeyboardJoypad::
;SGlib.c:382: unsigned char joypad=0;       // all keys not pressed unless some detection happens
	ld	c, #0x00
;SGlib.c:384: SC_PPI_C=0x06;                // we'll read row 6
	ld	a, #0x06
	out	(_SC_PPI_C), a
;SGlib.c:385: unsigned char tmp=SC_PPI_A;   // read kbd data
	in	a, (_SC_PPI_A)
;SGlib.c:386: if (!(tmp & 0x20))            // check bit 5 (right arrow key)
	bit	5, a
	jr	NZ, 00102$
;SGlib.c:387: joypad|=PORT_A_KEY_RIGHT;
	ld	c, #0x08
00102$:
;SGlib.c:388: if (!(tmp & 0x40))            // check bit 6 (up arrow key)
	bit	6, a
	jr	NZ, 00104$
;SGlib.c:389: joypad|=PORT_A_KEY_UP;
	set	0, c
00104$:
;SGlib.c:391: if (!(SC_PPI_B & 0x02))       // read kbd data (on PPI_B) and check bit 1 (Graph key)
	in	a, (_SC_PPI_B)
	bit	1, a
	jr	NZ, 00106$
;SGlib.c:392: joypad|=PORT_A_KEY_1;
	set	4, c
00106$:
;SGlib.c:394: SC_PPI_C=0x05;                // we'll read row 5
	ld	a, #0x05
	out	(_SC_PPI_C), a
;SGlib.c:395: if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (left arrow key)
	in	a, (_SC_PPI_A)
	bit	5, a
	jr	NZ, 00108$
;SGlib.c:396: joypad|=PORT_A_KEY_LEFT;
	set	2, c
00108$:
;SGlib.c:398: SC_PPI_C=0x04;                // we'll read row 4
	ld	a, #0x04
	out	(_SC_PPI_C), a
;SGlib.c:399: if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (down arrow key)
	in	a, (_SC_PPI_A)
	bit	5, a
	jr	NZ, 00110$
;SGlib.c:400: joypad|=PORT_A_KEY_DOWN;
	set	1, c
00110$:
;SGlib.c:402: SC_PPI_C=0x03;                // we'll read row 3
	ld	a, #0x03
	out	(_SC_PPI_C), a
;SGlib.c:403: if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Ins/Del key)
	in	a, (_SC_PPI_A)
	bit	4, a
	jr	NZ, 00112$
;SGlib.c:404: joypad|=PORT_A_KEY_2;
	set	5, c
00112$:
;SGlib.c:406: SC_PPI_C=0x02;                // we'll read row 2
	ld	a, #0x02
	out	(_SC_PPI_C), a
;SGlib.c:407: if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Home/Clr key)
	in	a, (_SC_PPI_A)
	bit	4, a
	jr	NZ, 00114$
;SGlib.c:408: joypad|=PORT_A_KEY_1;
	set	4, c
00114$:
;SGlib.c:410: SC_PPI_C=0x00;                // we'll read row 0
	ld	a, #0x00
	out	(_SC_PPI_C), a
;SGlib.c:411: if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Eng Dier's key)
	in	a, (_SC_PPI_A)
	bit	4, a
	jr	NZ, 00116$
;SGlib.c:412: joypad|=PORT_A_KEY_2;
	set	5, c
00116$:
;SGlib.c:414: SC_PPI_C=0x07;                // set row 7 (joypad) as default
	ld	a, #0x07
	out	(_SC_PPI_C), a
;SGlib.c:415: return joypad;
	ld	a, c
;SGlib.c:416: }
	ret

not sure about the name of the function, though 🤔

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

Are there two different keyboard keys that gets mapped to the right trigger? 🤔

edit: ... and also two for left trigger? Should I consider both?

"Official" Sega keyboard keys (99% of the games) used for games are: Arrows + "Home/CLR" (Fire 1) + "Ins/DEL" (Fire 2).

I added "Graph" and "Eng Dier's" only because is more comfortable. In some 2 players games "Graph" and "Eng Dier's" are used as Fires for player 2 with AWSD as cursors.

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

OK I think this should be correct:

unsigned char SG_readKeyboardJoypad (void) {
  unsigned char joypad=0;       // all keys not pressed unless some detection happens

  SC_PPI_C=0x06;                // we'll read row 6
  unsigned char tmp=SC_PPI_A;   // read kbd data
  if (!(tmp & 0x20))            // check bit 5 (right arrow key)
    joypad|=PORT_A_KEY_RIGHT;
  if (!(tmp & 0x40))            // check bit 6 (up arrow key)
    joypad|=PORT_A_KEY_UP;

  if (!(SC_PPI_B & 0x02))       // read kbd data (on PPI_B) and check bit 1 (Graph key)
    joypad|=PORT_A_KEY_1;

  SC_PPI_C=0x05;                // we'll read row 5
  if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (left arrow key)
    joypad|=PORT_A_KEY_LEFT;

  SC_PPI_C=0x04;                // we'll read row 4
  if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (down arrow key)
    joypad|=PORT_A_KEY_DOWN;

  SC_PPI_C=0x03;                // we'll read row 3
  if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Ins/Del key)
    joypad|=PORT_A_KEY_2;

  SC_PPI_C=0x02;                // we'll read row 2
  if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Home/Clr key)
    joypad|=PORT_A_KEY_1;

  SC_PPI_C=0x00;                // we'll read row 0
  if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Eng Dier's key)
    joypad|=PORT_A_KEY_2;

  SC_PPI_C=0x07;                // set row 7 (joypad) as default
  return joypad;
}

which turns into:

;SGlib.c:381: unsigned char SG_readKeyboardJoypad (void) {
;	---------------------------------
; Function SG_readKeyboardJoypad
; ---------------------------------
_SG_readKeyboardJoypad::
;SGlib.c:382: unsigned char joypad=0;       // all keys not pressed unless some detection happens
	ld	c, #0x00
;SGlib.c:384: SC_PPI_C=0x06;                // we'll read row 6
	ld	a, #0x06
	out	(_SC_PPI_C), a
;SGlib.c:385: unsigned char tmp=SC_PPI_A;   // read kbd data
	in	a, (_SC_PPI_A)
;SGlib.c:386: if (!(tmp & 0x20))            // check bit 5 (right arrow key)
	bit	5, a
	jr	NZ, 00102$
;SGlib.c:387: joypad|=PORT_A_KEY_RIGHT;
	ld	c, #0x08
00102$:
;SGlib.c:388: if (!(tmp & 0x40))            // check bit 6 (up arrow key)
	bit	6, a
	jr	NZ, 00104$
;SGlib.c:389: joypad|=PORT_A_KEY_UP;
	set	0, c
00104$:
;SGlib.c:391: if (!(SC_PPI_B & 0x02))       // read kbd data (on PPI_B) and check bit 1 (Graph key)
	in	a, (_SC_PPI_B)
	bit	1, a
	jr	NZ, 00106$
;SGlib.c:392: joypad|=PORT_A_KEY_1;
	set	4, c
00106$:
;SGlib.c:394: SC_PPI_C=0x05;                // we'll read row 5
	ld	a, #0x05
	out	(_SC_PPI_C), a
;SGlib.c:395: if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (left arrow key)
	in	a, (_SC_PPI_A)
	bit	5, a
	jr	NZ, 00108$
;SGlib.c:396: joypad|=PORT_A_KEY_LEFT;
	set	2, c
00108$:
;SGlib.c:398: SC_PPI_C=0x04;                // we'll read row 4
	ld	a, #0x04
	out	(_SC_PPI_C), a
;SGlib.c:399: if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (down arrow key)
	in	a, (_SC_PPI_A)
	bit	5, a
	jr	NZ, 00110$
;SGlib.c:400: joypad|=PORT_A_KEY_DOWN;
	set	1, c
00110$:
;SGlib.c:402: SC_PPI_C=0x03;                // we'll read row 3
	ld	a, #0x03
	out	(_SC_PPI_C), a
;SGlib.c:403: if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Ins/Del key)
	in	a, (_SC_PPI_A)
	bit	4, a
	jr	NZ, 00112$
;SGlib.c:404: joypad|=PORT_A_KEY_2;
	set	5, c
00112$:
;SGlib.c:406: SC_PPI_C=0x02;                // we'll read row 2
	ld	a, #0x02
	out	(_SC_PPI_C), a
;SGlib.c:407: if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Home/Clr key)
	in	a, (_SC_PPI_A)
	bit	4, a
	jr	NZ, 00114$
;SGlib.c:408: joypad|=PORT_A_KEY_1;
	set	4, c
00114$:
;SGlib.c:410: SC_PPI_C=0x00;                // we'll read row 0
	ld	a, #0x00
	out	(_SC_PPI_C), a
;SGlib.c:411: if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Eng Dier's key)
	in	a, (_SC_PPI_A)
	bit	4, a
	jr	NZ, 00116$
;SGlib.c:412: joypad|=PORT_A_KEY_2;
	set	5, c
00116$:
;SGlib.c:414: SC_PPI_C=0x07;                // set row 7 (joypad) as default
	ld	a, #0x07
	out	(_SC_PPI_C), a
;SGlib.c:415: return joypad;
	ld	a, c
;SGlib.c:416: }
	ret

not sure about the name of the function, though 🤔

It looks correct and fast enough!

The name for this function? JoyReadKbd or JoyKRead ?

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

OK I think this should be correct:

unsigned char SG_readKeyboardJoypad (void) {
  unsigned char joypad=0;       // all keys not pressed unless some detection happens

  SC_PPI_C=0x06;                // we'll read row 6
  unsigned char tmp=SC_PPI_A;   // read kbd data
  if (!(tmp & 0x20))            // check bit 5 (right arrow key)
    joypad|=PORT_A_KEY_RIGHT;
  if (!(tmp & 0x40))            // check bit 6 (up arrow key)
    joypad|=PORT_A_KEY_UP;

  if (!(SC_PPI_B & 0x02))       // read kbd data (on PPI_B) and check bit 1 (Graph key)
    joypad|=PORT_A_KEY_1;

  SC_PPI_C=0x05;                // we'll read row 5
  if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (left arrow key)
    joypad|=PORT_A_KEY_LEFT;

  SC_PPI_C=0x04;                // we'll read row 4
  if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (down arrow key)
    joypad|=PORT_A_KEY_DOWN;

  SC_PPI_C=0x03;                // we'll read row 3
  if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Ins/Del key)
    joypad|=PORT_A_KEY_2;

  SC_PPI_C=0x02;                // we'll read row 2
  if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Home/Clr key)
    joypad|=PORT_A_KEY_1;

  SC_PPI_C=0x00;                // we'll read row 0
  if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Eng Dier's key)
    joypad|=PORT_A_KEY_2;

  SC_PPI_C=0x07;                // set row 7 (joypad) as default
  return joypad;
}

which turns into:

;SGlib.c:381: unsigned char SG_readKeyboardJoypad (void) {
;	---------------------------------
; Function SG_readKeyboardJoypad
; ---------------------------------
_SG_readKeyboardJoypad::
;SGlib.c:382: unsigned char joypad=0;       // all keys not pressed unless some detection happens
	ld	c, #0x00
;SGlib.c:384: SC_PPI_C=0x06;                // we'll read row 6
	ld	a, #0x06
	out	(_SC_PPI_C), a
;SGlib.c:385: unsigned char tmp=SC_PPI_A;   // read kbd data
	in	a, (_SC_PPI_A)
;SGlib.c:386: if (!(tmp & 0x20))            // check bit 5 (right arrow key)
	bit	5, a
	jr	NZ, 00102$
;SGlib.c:387: joypad|=PORT_A_KEY_RIGHT;
	ld	c, #0x08
00102$:
;SGlib.c:388: if (!(tmp & 0x40))            // check bit 6 (up arrow key)
	bit	6, a
	jr	NZ, 00104$
;SGlib.c:389: joypad|=PORT_A_KEY_UP;
	set	0, c
00104$:
;SGlib.c:391: if (!(SC_PPI_B & 0x02))       // read kbd data (on PPI_B) and check bit 1 (Graph key)
	in	a, (_SC_PPI_B)
	bit	1, a
	jr	NZ, 00106$
;SGlib.c:392: joypad|=PORT_A_KEY_1;
	set	4, c
00106$:
;SGlib.c:394: SC_PPI_C=0x05;                // we'll read row 5
	ld	a, #0x05
	out	(_SC_PPI_C), a
;SGlib.c:395: if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (left arrow key)
	in	a, (_SC_PPI_A)
	bit	5, a
	jr	NZ, 00108$
;SGlib.c:396: joypad|=PORT_A_KEY_LEFT;
	set	2, c
00108$:
;SGlib.c:398: SC_PPI_C=0x04;                // we'll read row 4
	ld	a, #0x04
	out	(_SC_PPI_C), a
;SGlib.c:399: if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (down arrow key)
	in	a, (_SC_PPI_A)
	bit	5, a
	jr	NZ, 00110$
;SGlib.c:400: joypad|=PORT_A_KEY_DOWN;
	set	1, c
00110$:
;SGlib.c:402: SC_PPI_C=0x03;                // we'll read row 3
	ld	a, #0x03
	out	(_SC_PPI_C), a
;SGlib.c:403: if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Ins/Del key)
	in	a, (_SC_PPI_A)
	bit	4, a
	jr	NZ, 00112$
;SGlib.c:404: joypad|=PORT_A_KEY_2;
	set	5, c
00112$:
;SGlib.c:406: SC_PPI_C=0x02;                // we'll read row 2
	ld	a, #0x02
	out	(_SC_PPI_C), a
;SGlib.c:407: if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Home/Clr key)
	in	a, (_SC_PPI_A)
	bit	4, a
	jr	NZ, 00114$
;SGlib.c:408: joypad|=PORT_A_KEY_1;
	set	4, c
00114$:
;SGlib.c:410: SC_PPI_C=0x00;                // we'll read row 0
	ld	a, #0x00
	out	(_SC_PPI_C), a
;SGlib.c:411: if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Eng Dier's key)
	in	a, (_SC_PPI_A)
	bit	4, a
	jr	NZ, 00116$
;SGlib.c:412: joypad|=PORT_A_KEY_2;
	set	5, c
00116$:
;SGlib.c:414: SC_PPI_C=0x07;                // set row 7 (joypad) as default
	ld	a, #0x07
	out	(_SC_PPI_C), a
;SGlib.c:415: return joypad;
	ld	a, c
;SGlib.c:416: }
	ret

not sure about the name of the function, though 🤔

Look correct and fast enough!

The name for this function? JoyReadKbd or JoyKRead ?

OK I think this should be correct:

unsigned char SG_readKeyboardJoypad (void) {
  unsigned char joypad=0;       // all keys not pressed unless some detection happens

  SC_PPI_C=0x06;                // we'll read row 6
  unsigned char tmp=SC_PPI_A;   // read kbd data
  if (!(tmp & 0x20))            // check bit 5 (right arrow key)
    joypad|=PORT_A_KEY_RIGHT;
  if (!(tmp & 0x40))            // check bit 6 (up arrow key)
    joypad|=PORT_A_KEY_UP;

  if (!(SC_PPI_B & 0x02))       // read kbd data (on PPI_B) and check bit 1 (Graph key)
    joypad|=PORT_A_KEY_1;

  SC_PPI_C=0x05;                // we'll read row 5
  if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (left arrow key)
    joypad|=PORT_A_KEY_LEFT;

  SC_PPI_C=0x04;                // we'll read row 4
  if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (down arrow key)
    joypad|=PORT_A_KEY_DOWN;

  SC_PPI_C=0x03;                // we'll read row 3
  if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Ins/Del key)
    joypad|=PORT_A_KEY_2;

  SC_PPI_C=0x02;                // we'll read row 2
  if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Home/Clr key)
    joypad|=PORT_A_KEY_1;

  SC_PPI_C=0x00;                // we'll read row 0
  if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Eng Dier's key)
    joypad|=PORT_A_KEY_2;

  SC_PPI_C=0x07;                // set row 7 (joypad) as default
  return joypad;
}

which turns into:

;SGlib.c:381: unsigned char SG_readKeyboardJoypad (void) {
;	---------------------------------
; Function SG_readKeyboardJoypad
; ---------------------------------
_SG_readKeyboardJoypad::
;SGlib.c:382: unsigned char joypad=0;       // all keys not pressed unless some detection happens
	ld	c, #0x00
;SGlib.c:384: SC_PPI_C=0x06;                // we'll read row 6
	ld	a, #0x06
	out	(_SC_PPI_C), a
;SGlib.c:385: unsigned char tmp=SC_PPI_A;   // read kbd data
	in	a, (_SC_PPI_A)
;SGlib.c:386: if (!(tmp & 0x20))            // check bit 5 (right arrow key)
	bit	5, a
	jr	NZ, 00102$
;SGlib.c:387: joypad|=PORT_A_KEY_RIGHT;
	ld	c, #0x08
00102$:
;SGlib.c:388: if (!(tmp & 0x40))            // check bit 6 (up arrow key)
	bit	6, a
	jr	NZ, 00104$
;SGlib.c:389: joypad|=PORT_A_KEY_UP;
	set	0, c
00104$:
;SGlib.c:391: if (!(SC_PPI_B & 0x02))       // read kbd data (on PPI_B) and check bit 1 (Graph key)
	in	a, (_SC_PPI_B)
	bit	1, a
	jr	NZ, 00106$
;SGlib.c:392: joypad|=PORT_A_KEY_1;
	set	4, c
00106$:
;SGlib.c:394: SC_PPI_C=0x05;                // we'll read row 5
	ld	a, #0x05
	out	(_SC_PPI_C), a
;SGlib.c:395: if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (left arrow key)
	in	a, (_SC_PPI_A)
	bit	5, a
	jr	NZ, 00108$
;SGlib.c:396: joypad|=PORT_A_KEY_LEFT;
	set	2, c
00108$:
;SGlib.c:398: SC_PPI_C=0x04;                // we'll read row 4
	ld	a, #0x04
	out	(_SC_PPI_C), a
;SGlib.c:399: if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (down arrow key)
	in	a, (_SC_PPI_A)
	bit	5, a
	jr	NZ, 00110$
;SGlib.c:400: joypad|=PORT_A_KEY_DOWN;
	set	1, c
00110$:
;SGlib.c:402: SC_PPI_C=0x03;                // we'll read row 3
	ld	a, #0x03
	out	(_SC_PPI_C), a
;SGlib.c:403: if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Ins/Del key)
	in	a, (_SC_PPI_A)
	bit	4, a
	jr	NZ, 00112$
;SGlib.c:404: joypad|=PORT_A_KEY_2;
	set	5, c
00112$:
;SGlib.c:406: SC_PPI_C=0x02;                // we'll read row 2
	ld	a, #0x02
	out	(_SC_PPI_C), a
;SGlib.c:407: if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Home/Clr key)
	in	a, (_SC_PPI_A)
	bit	4, a
	jr	NZ, 00114$
;SGlib.c:408: joypad|=PORT_A_KEY_1;
	set	4, c
00114$:
;SGlib.c:410: SC_PPI_C=0x00;                // we'll read row 0
	ld	a, #0x00
	out	(_SC_PPI_C), a
;SGlib.c:411: if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Eng Dier's key)
	in	a, (_SC_PPI_A)
	bit	4, a
	jr	NZ, 00116$
;SGlib.c:412: joypad|=PORT_A_KEY_2;
	set	5, c
00116$:
;SGlib.c:414: SC_PPI_C=0x07;                // set row 7 (joypad) as default
	ld	a, #0x07
	out	(_SC_PPI_C), a
;SGlib.c:415: return joypad;
	ld	a, c
;SGlib.c:416: }
	ret

not sure about the name of the function, though 🤔

It looks correct and fast enough!

The name for this function? JoyReadKbd or JoyKRead ?

Or AddKBDJoyKeys ?

from devkitsms.

sverx avatar sverx commented on July 28, 2024

"Official" Sega keyboard keys (99% of the games) used for games are: Arrows + "Home/CLR" (Fire 1) + "Ins/DEL" (Fire 2).
I added "Graph" and "Eng Dier's" only because is more comfortable. In some 2 players games "Graph" and "Eng Dier's" are used as Fires for player 2 with AWSD as cursors.

So the function should probably instead read both 'virtual' joypads? It could return the same data as the function that reads the physical joypads. So maybe then a good name for the function could be something like SG_readKeyboardJoypads to imply that we're using the keyboard as virtual joypad(s). I feel like it would be more flexible as someone might want to code a two players game, or code a 1-player game that accepts buttons for any player.

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

"Official" Sega keyboard keys (99% of the games) used for games are: Arrows + "Home/CLR" (Fire 1) + "Ins/DEL" (Fire 2).
I added "Graph" and "Eng Dier's" only because is more comfortable. In some 2 players games "Graph" and "Eng Dier's" are used as Fires for player 2 with AWSD as cursors.

So the function should probably instead read both 'virtual' joypads? It could return the same data as the function that reads the physical joypads. So maybe then a good name for the function could be something like SG_readKeyboardJoypads to imply that we're using the keyboard as virtual joypad(s). I feel like it would be more flexible as someone might want to code a two players game, or code a 1-player game that accepts buttons for any player.

Yes. Virtual Joystick is correct.

Don't forget that PortA for 7th row (joypad) contains data of player 1 but also fire buttons of player 2.
This is why I propose to manage a 16 byte buffer for entire matrix (joypad + keyboard).

from devkitsms.

sverx avatar sverx commented on July 28, 2024

Don't forget that PortA for 7th row (joypad) contains data of player 1 but also fire buttons of player 2. This is why I propose to > manage a 16 byte buffer for entire matrix (joypad + keyboard).

We could add some more advanced functions later to address that.

from devkitsms.

sverx avatar sverx commented on July 28, 2024

OK so I made it very similar to how the joypads work in the SG and the SMS.

There's one function that needs to be called regularly (say once a frame) SG_scanKeyboardJoypad to make sure keys pressures/depressures are detected and then there are 4 functions to check the current status of the virtual joypads, if a button is being just pressed or held down or released: SG_getKeyboardJoypadStatus, SG_getKeyboardJoypadPressed, SG_getKeyboardJoypadHeld and SG_getKeyboardJoypadReleased. They all work exactly like their real joypads counterparts.

So this means one can even actually code a 4 player game, two using the real joypads and two using the 'virtual' ones 😄

void SG_scanKeyboardJoypad (void) {
  unsigned char tmp;

  KBDPreviousKeysStatus=KBDKeysStatus;
  KBDKeysStatus=0;              // all keys not pressed unless some detection happens

  SC_PPI_C=0x06;                // we'll read row 6
  tmp=SC_PPI_A;                 // read kbd data
  if (!(tmp & 0x20))            // check bit 5 (right arrow key)
    KBDKeysStatus|=PORT_A_KEY_RIGHT;
  if (!(tmp & 0x40))            // check bit 6 (up arrow key)
    KBDKeysStatus|=PORT_A_KEY_UP;

  if (!(SC_PPI_B & 0x02))       // read kbd data (on PPI_B) and check bit 1 (Graph key)
    KBDKeysStatus|=PORT_B_KEY_1;

  SC_PPI_C=0x05;                // we'll read row 5
  if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (left arrow key)
    KBDKeysStatus|=PORT_A_KEY_LEFT;

  SC_PPI_C=0x04;                // we'll read row 4
  if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (down arrow key)
    KBDKeysStatus|=PORT_A_KEY_DOWN;

  SC_PPI_C=0x03;                // we'll read row 3
  if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Ins/Del key)
    KBDKeysStatus|=PORT_A_KEY_2;

  SC_PPI_C=0x02;                // we'll read row 2
  tmp=SC_PPI_A;                 // read kbd data
  if (!(tmp & 0x10))            // read kbd data and check bit 4 (Home/Clr key)
    KBDKeysStatus|=PORT_A_KEY_1;
  if (!(tmp & 0x04))            // read kbd data and check bit 2 ('D' key)
    KBDKeysStatus|=PORT_B_KEY_LEFT;

  SC_PPI_C=0x01;                // we'll read row 1
  tmp=SC_PPI_A;                 // read kbd data
  if (!(tmp & 0x02))            // read kbd data and check bit 1 ('W' key)
    KBDKeysStatus|=PORT_B_KEY_UP;
  if (!(tmp & 0x04))            // read kbd data and check bit 2 ('S' key)
    KBDKeysStatus|=PORT_B_KEY_DOWN;

  SC_PPI_C=0x00;                // we'll read row 0
  tmp=SC_PPI_A;                 // read kbd data
  if (!(tmp & 0x10))            // read kbd data and check bit 4 (Eng Dier's key)
    KBDKeysStatus|=PORT_B_KEY_2;
  if (!(tmp & 0x04))            // read kbd data and check bit 2 ('A' key)
    KBDKeysStatus|=PORT_B_KEY_RIGHT;

  SC_PPI_C=0x07;                // set row 7 (KBDKeysStatus) as default
}

unsigned int SG_getKeyboardJoypadStatus (void) {
  return (KBDKeysStatus);
}

unsigned int SG_getKeyboardJoypadPressed (void) {
  return (KBDKeysStatus & (~KBDPreviousKeysStatus));
}

unsigned int SG_getKeyboardJoypadHeld (void) {
  return (KBDKeysStatus & KBDPreviousKeysStatus);
}

unsigned int SG_getKeyboardJoypadReleased (void) {
  return ((~KBDKeysStatus) & KBDPreviousKeysStatus);
}

from devkitsms.

sverx avatar sverx commented on July 28, 2024

Improved code size and speed by not writing to RAM until the whole operation is done:

void SG_scanKeyboardJoypad (void) {
  unsigned char tmp;
  unsigned int status=0;        // all keys not pressed unless some detection happens

  SC_PPI_C=0x06;                // we'll read row 6
  tmp=SC_PPI_A;                 // read kbd data
  if (!(tmp & 0x20))            // check bit 5 (right arrow key)
    status|=PORT_A_KEY_RIGHT;
  if (!(tmp & 0x40))            // check bit 6 (up arrow key)
    status|=PORT_A_KEY_UP;

  if (!(SC_PPI_B & 0x02))       // read kbd data (on PPI_B) and check bit 1 (Graph key)
    status|=PORT_B_KEY_1;

  SC_PPI_C=0x05;                // we'll read row 5
  if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (left arrow key)
    status|=PORT_A_KEY_LEFT;

  SC_PPI_C=0x04;                // we'll read row 4
  if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (down arrow key)
    status|=PORT_A_KEY_DOWN;

  SC_PPI_C=0x03;                // we'll read row 3
  if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Ins/Del key)
    status|=PORT_A_KEY_2;

  SC_PPI_C=0x02;                // we'll read row 2
  tmp=SC_PPI_A;                 // read kbd data
  if (!(tmp & 0x10))            // read kbd data and check bit 4 (Home/Clr key)
    status|=PORT_A_KEY_1;
  if (!(tmp & 0x04))            // read kbd data and check bit 2 ('D' key)
    status|=PORT_B_KEY_LEFT;

  SC_PPI_C=0x01;                // we'll read row 1
  tmp=SC_PPI_A;                 // read kbd data
  if (!(tmp & 0x02))            // read kbd data and check bit 1 ('W' key)
    status|=PORT_B_KEY_UP;
  if (!(tmp & 0x04))            // read kbd data and check bit 2 ('S' key)
    status|=PORT_B_KEY_DOWN;

  SC_PPI_C=0x00;                // we'll read row 0
  tmp=SC_PPI_A;                 // read kbd data
  if (!(tmp & 0x10))            // read kbd data and check bit 4 (Eng Dier's key)
    status|=PORT_B_KEY_2;
  if (!(tmp & 0x04))            // read kbd data and check bit 2 ('A' key)
    status|=PORT_B_KEY_RIGHT;

  SC_PPI_C=0x07;                // set row 7 (KBDKeysStatus) as default

  KBDPreviousKeysStatus=KBDKeysStatus;
  KBDKeysStatus=status;
}

which compiles to:

;SGlib.c:382: void SG_scanKeyboardJoypad (void) {
;	---------------------------------
; Function SG_scanKeyboardJoypad
; ---------------------------------
_SG_scanKeyboardJoypad::
;SGlib.c:384: unsigned int status=0;        // all keys not pressed unless some detection happens
	ld	bc, #0x0000
;SGlib.c:386: SC_PPI_C=0x06;                // we'll read row 6
	ld	a, #0x06
	out	(_SC_PPI_C), a
;SGlib.c:387: tmp=SC_PPI_A;                 // read kbd data
	in	a, (_SC_PPI_A)
;SGlib.c:388: if (!(tmp & 0x20))            // check bit 5 (right arrow key)
	bit	5, a
	jr	NZ, 00102$
;SGlib.c:389: status|=PORT_A_KEY_RIGHT;
	ld	bc, #0x0008
00102$:
;SGlib.c:390: if (!(tmp & 0x40))            // check bit 6 (up arrow key)
	bit	6, a
	jr	NZ, 00104$
;SGlib.c:391: status|=PORT_A_KEY_UP;
	set	0, c
00104$:
;SGlib.c:393: if (!(SC_PPI_B & 0x02))       // read kbd data (on PPI_B) and check bit 1 (Graph key)
	in	a, (_SC_PPI_B)
	bit	1, a
	jr	NZ, 00106$
;SGlib.c:394: status|=PORT_B_KEY_1;
	set	2, b
00106$:
;SGlib.c:396: SC_PPI_C=0x05;                // we'll read row 5
	ld	a, #0x05
	out	(_SC_PPI_C), a
;SGlib.c:397: if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (left arrow key)
	in	a, (_SC_PPI_A)
	bit	5, a
	jr	NZ, 00108$
;SGlib.c:398: status|=PORT_A_KEY_LEFT;
	set	2, c
00108$:
;SGlib.c:400: SC_PPI_C=0x04;                // we'll read row 4
	ld	a, #0x04
	out	(_SC_PPI_C), a
;SGlib.c:401: if (!(SC_PPI_A & 0x20))       // read kbd data and check bit 5 (down arrow key)
	in	a, (_SC_PPI_A)
	bit	5, a
	jr	NZ, 00110$
;SGlib.c:402: status|=PORT_A_KEY_DOWN;
	set	1, c
00110$:
;SGlib.c:404: SC_PPI_C=0x03;                // we'll read row 3
	ld	a, #0x03
	out	(_SC_PPI_C), a
;SGlib.c:405: if (!(SC_PPI_A & 0x10))       // read kbd data and check bit 4 (Ins/Del key)
	in	a, (_SC_PPI_A)
	bit	4, a
	jr	NZ, 00112$
;SGlib.c:406: status|=PORT_A_KEY_2;
	set	5, c
00112$:
;SGlib.c:408: SC_PPI_C=0x02;                // we'll read row 2
	ld	a, #0x02
	out	(_SC_PPI_C), a
;SGlib.c:409: tmp=SC_PPI_A;                 // read kbd data
	in	a, (_SC_PPI_A)
;SGlib.c:410: if (!(tmp & 0x10))            // read kbd data and check bit 4 (Home/Clr key)
	bit	4, a
	jr	NZ, 00114$
;SGlib.c:411: status|=PORT_A_KEY_1;
	set	4, c
00114$:
;SGlib.c:412: if (!(tmp & 0x04))            // read kbd data and check bit 2 ('D' key)
	bit	2, a
	jr	NZ, 00116$
;SGlib.c:413: status|=PORT_B_KEY_LEFT;
	set	0, b
00116$:
;SGlib.c:415: SC_PPI_C=0x01;                // we'll read row 1
	ld	a, #0x01
	out	(_SC_PPI_C), a
;SGlib.c:416: tmp=SC_PPI_A;                 // read kbd data
	in	a, (_SC_PPI_A)
;SGlib.c:417: if (!(tmp & 0x02))            // read kbd data and check bit 1 ('W' key)
	bit	1, a
	jr	NZ, 00118$
;SGlib.c:418: status|=PORT_B_KEY_UP;
	set	6, c
00118$:
;SGlib.c:419: if (!(tmp & 0x04))            // read kbd data and check bit 2 ('S' key)
	bit	2, a
	jr	NZ, 00120$
;SGlib.c:420: status|=PORT_B_KEY_DOWN;
	set	7, c
00120$:
;SGlib.c:422: SC_PPI_C=0x00;                // we'll read row 0
	ld	a, #0x00
	out	(_SC_PPI_C), a
;SGlib.c:423: tmp=SC_PPI_A;                 // read kbd data
	in	a, (_SC_PPI_A)
;SGlib.c:424: if (!(tmp & 0x10))            // read kbd data and check bit 4 (Eng Dier's key)
	bit	4, a
	jr	NZ, 00122$
;SGlib.c:425: status|=PORT_B_KEY_2;
	set	3, b
00122$:
;SGlib.c:426: if (!(tmp & 0x04))            // read kbd data and check bit 2 ('A' key)
	bit	2, a
	jr	NZ, 00124$
;SGlib.c:427: status|=PORT_B_KEY_RIGHT;
	set	1, b
00124$:
;SGlib.c:429: SC_PPI_C=0x07;                // set row 7 (KBDKeysStatus) as default
	ld	a, #0x07
	out	(_SC_PPI_C), a
;SGlib.c:431: KBDPreviousKeysStatus=KBDKeysStatus;
	ld	hl, (_KBDKeysStatus)
	ld	(_KBDPreviousKeysStatus), hl
;SGlib.c:432: KBDKeysStatus=status;
	ld	(_KBDKeysStatus), bc
;SGlib.c:433: }
	ret

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

from devkitsms.

sverx avatar sverx commented on July 28, 2024

Thanks, I'll publish it ASAP.

E magari se mi accorgevo prima che sei italiano anche tu mi evitavo anche la fatica di scrivere tutto in inglese 🤣 🙄

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

from devkitsms.

sverx avatar sverx commented on July 28, 2024

No, non ho nessun hardware a disposizione.

Vedrò di creare una ROM, ci vorrà un po' perché non ho mai usato questa specifica libreria (che in effetti è un fork che non ho creato io...)

O altrimenti... tu pensavi di usarla o volevi solo prendere parte allo sviluppo?

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

from devkitsms.

sverx avatar sverx commented on July 28, 2024

OK I had swapped left and right keys but now this should work (at least it does in MEKA!)

image

KDBJoyTest.sg.zip

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

from devkitsms.

sverx avatar sverx commented on July 28, 2024

So the triggers for the player 2 on the keyboard should not be the "Graph" and "Eng Dier's" keys but the "Func" and "Ctrl" keys instead?

And those two won't mess with the other keys? 🤔

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

from devkitsms.

sverx avatar sverx commented on July 28, 2024

Player 1, Fire 1 and 2 are inverted as well. Ins-Del is Fire 1.

Really? Isn't Fire1 supposed to be the left trigger? So shouldn't it be the one on the left? 🤔

image

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

from devkitsms.

sverx avatar sverx commented on July 28, 2024

Yes, I also attached a picture of the SK-1100 above.

Since the Home-Clr key is the leftmost of those two, then it should be mapped to the left trigger, why the opposite? 🤔

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

from devkitsms.

sverx avatar sverx commented on July 28, 2024

I fail to see where it describes which is which.
https://segaretro.org/index.php?title=File:Champion_Tennis_SG1000_AU_Manual.pdf&page=3

In my opinion it makes more sense to me to map the leftmost of the two keys (Home) to the left trigger.

But if you find some evidence that it's not how SEGA meant to use this I can swap them!

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

from devkitsms.

sverx avatar sverx commented on July 28, 2024

OK this should fix player 2 left and right trigger too.

KDBJoyTest.sg.zip

from devkitsms.

sverx avatar sverx commented on July 28, 2024

Whenever you've got some time please confirm this is working fine so that I can push it to the repository.

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

from devkitsms.

sverx avatar sverx commented on July 28, 2024

Of course I had uploaded the wrong file... 😅

Try this:

KDBJoyTest.sg.zip

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

from devkitsms.

sverx avatar sverx commented on July 28, 2024

Committed to the repository!

I'll close this issue now, as it's already pretty long. If there's something else we could add let's open a new issue.

E grazie! 😃
👋

from devkitsms.

siriokds avatar siriokds commented on July 28, 2024

from devkitsms.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.