sverx / devkitSMS

development kit and libraries for SEGA Master System / SEGA Game Gear / SEGA SG-1000 / SEGA SC-3000 homebrew programming using C language (and the SDCC compiler)
229 stars 34 forks source link

SG-1000 ROMs on SC-3000 - Sega standard. #36

Closed siriokds closed 2 years ago

siriokds commented 2 years ago

There are a few mods to support SC-3000 in SG-1000. I can send you some mod to let the roms be full compatible.

S.

sverx commented 2 years ago

Sure! Send them over! :heart:

siriokds commented 2 years ago

Sure! Send them over! ❤️

How can I send you my mods?

siriokds commented 2 years ago

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)

siriokds commented 2 years ago

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

siriokds commented 2 years ago

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

sverx commented 2 years ago

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.

siriokds commented 2 years ago

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

sverx commented 2 years ago

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!

siriokds commented 2 years ago

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.

sverx commented 2 years ago

https://github.com/sverx/devkitSMS/commit/cf35965f34fb418361b2674e364634e47492700b

Done.

What's next?

sverx commented 2 years ago

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?

siriokds commented 2 years ago

cf35965

Done.

What's next?

Cool.

siriokds commented 2 years ago

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.

siriokds commented 2 years ago

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.

sverx commented 2 years ago

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?

siriokds commented 2 years ago

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

Il lun 22 ago 2022, 09:37 sverx @.***> ha scritto:

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?

— Reply to this email directly, view it on GitHub https://github.com/sverx/devkitSMS/issues/36#issuecomment-1221968762, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABZCLIGK6EGJH5MY6AX6RMDV2MU3HANCNFSM56LEACJA . You are receiving this because you authored the thread.Message ID: @.***>

sverx commented 2 years ago

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

So the official SEGA detection routine had delays? :thinking:

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$
siriokds commented 2 years ago

No delay. Your code should works but I need to see the generated assembly obviously. If you want add delay between the write value to port C and the readback, insert one nop, but I don't do this in assembly. Usually I insert this routines in CRT0 because are working for SG as well SC.

Il lun 22 ago 2022, 10:27 sverx @.***> ha scritto:

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$

— Reply to this email directly, view it on GitHub https://github.com/sverx/devkitSMS/issues/36#issuecomment-1222023107, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABZCLICEGXJ6VBWQBAIRXMLV2M2YDANCNFSM56LEACJA . You are receiving this because you authored the thread.Message ID: @.***>

sverx commented 2 years ago

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 :smiley:

siriokds commented 2 years ago

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

sverx commented 2 years ago

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

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?

siriokds commented 2 years ago

If you read my code you can see that the first operation to read merged data is to check the keyboard present variable.

If that variable value is zero, it acts reading only the joypad value ELSE it merge the keyboard data to the joypad data read before. Indeed you can separate the 2 routine or if you want I can do it for you.

Il gio 25 ago 2022, 09:20 sverx @.***> ha scritto:

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?

— Reply to this email directly, view it on GitHub https://github.com/sverx/devkitSMS/issues/36#issuecomment-1226873827, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABZCLIBELQ7WQTNTOXQHKDLV24NC5ANCNFSM56LEACJA . You are receiving this because you authored the thread.Message ID: @.***>

sverx commented 2 years ago

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 :wave:

siriokds commented 2 years ago

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

sverx commented 2 years ago

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! :wave:

sverx commented 2 years ago

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

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

sverx commented 2 years ago

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 :thinking:

siriokds commented 2 years ago

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.

siriokds commented 2 years ago

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 ?

siriokds commented 2 years ago

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 ?

sverx commented 2 years ago

"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.

siriokds commented 2 years ago

"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).

sverx commented 2 years ago

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.

sverx commented 2 years ago

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 :smile:

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);
}
sverx commented 2 years ago

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
siriokds commented 2 years ago

Nice idea the 4 player support!

Il giorno ven 26 ago 2022 alle ore 12:14 sverx @.***> ha scritto:

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);

}

— Reply to this email directly, view it on GitHub https://github.com/sverx/devkitSMS/issues/36#issuecomment-1228317095, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABZCLICAY3MVTPYSBGFDWKTV3CKIXANCNFSM56LEACJA . You are receiving this because you authored the thread.Message ID: @.***>

-- Dott. Saverio Russo Software Architect LinkedIn page url: http://www.linkedin.com/in/sarusso

E-mail: @.***

PEC: @.*** Website: http://www.saveriorusso.com

The information transmitted is intended only for the person(s) or entity to which it is addressed and may contain confidential and/or privileged material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please contact the sender and delete the material from any computer.

siriokds commented 2 years ago

This, looks like a release version! :)

Il giorno ven 26 ago 2022 alle ore 12:22 sverx @.***> ha scritto:

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

— Reply to this email directly, view it on GitHub https://github.com/sverx/devkitSMS/issues/36#issuecomment-1228323833, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABZCLIGXTWHUV7H6SHXJZF3V3CLGNANCNFSM56LEACJA . You are receiving this because you authored the thread.Message ID: @.***>

-- Dott. Saverio Russo Software Architect LinkedIn page url: http://www.linkedin.com/in/sarusso

E-mail: @.***

PEC: @.*** Website: http://www.saveriorusso.com

The information transmitted is intended only for the person(s) or entity to which it is addressed and may contain confidential and/or privileged material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please contact the sender and delete the material from any computer.

sverx commented 2 years ago

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 :rofl: :roll_eyes:

siriokds commented 2 years ago

Ahahahha, vabbè ci si tiene in allenamento.

Se hai hardware su cui provare ottimo, altrimenti mi generi una rom e te la provo io.

S.

Il giorno ven 26 ago 2022 alle ore 17:16 sverx @.***> ha scritto:

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 🤣 🙄

— Reply to this email directly, view it on GitHub https://github.com/sverx/devkitSMS/issues/36#issuecomment-1228623872, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABZCLIFFTNXXEJ65DA7SCZLV3DNWDANCNFSM56LEACJA . You are receiving this because you authored the thread.Message ID: @.***>

-- Dott. Saverio Russo Software Architect LinkedIn page url: http://www.linkedin.com/in/sarusso

E-mail: @.***

PEC: @.*** Website: http://www.saveriorusso.com

The information transmitted is intended only for the person(s) or entity to which it is addressed and may contain confidential and/or privileged material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please contact the sender and delete the material from any computer.

sverx commented 2 years ago

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?

siriokds commented 2 years ago

Momentaneamente non la sto usando. Ne avevo fatta una io prendendo pezzi da MsxGL. Di solito uso l'assembly ma ci sono tante persone che la usano.

Se mi mandi una "demo" che mostra la presenza o meno della tastiera e la usa insieme al joystick, posso provarla su veri SC-3000 ed SG-1000.

S.

Il ven 26 ago 2022, 17:49 sverx @.***> ha scritto:

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?

— Reply to this email directly, view it on GitHub https://github.com/sverx/devkitSMS/issues/36#issuecomment-1228661005, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABZCLICYXUYRV4A73SWKMBLV3DRQ5ANCNFSM56LEACJA . You are receiving this because you authored the thread.Message ID: @.***>

sverx commented 2 years ago

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

image

KDBJoyTest.sg.zip

siriokds commented 2 years ago

It works well on SC-3000. I need to test it on SG.

I was wrong on SC-3000 player 2 keys:

Fire 1 and 2 for player 2 are "Func" and "Ctrl" keys (more comfortable).

For movements for player 2, Sega uses EXSF but I think WSAD combo is far better (PC standard).

Il giorno ven 26 ago 2022 alle ore 23:18 sverx @.***> ha scritto:

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

[image: image] https://user-images.githubusercontent.com/6738932/186991974-c1ccfd3f-39e5-461e-9cd2-de721aea1b7e.png

KDBJoyTest.sg.zip https://github.com/sverx/devkitSMS/files/9436457/KDBJoyTest.sg.zip

— Reply to this email directly, view it on GitHub https://github.com/sverx/devkitSMS/issues/36#issuecomment-1228956858, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABZCLIBEOM3QHN3C2AHEBATV3EYA7ANCNFSM56LEACJA . You are receiving this because you authored the thread.Message ID: @.***>

-- Dott. Saverio Russo Software Architect LinkedIn page url: http://www.linkedin.com/in/sarusso

E-mail: @.***

PEC: @.*** Website: http://www.saveriorusso.com

The information transmitted is intended only for the person(s) or entity to which it is addressed and may contain confidential and/or privileged material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please contact the sender and delete the material from any computer.

sverx commented 2 years ago

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? :thinking:

siriokds commented 2 years ago

Sorry, my old mind fails sometimes. Graph+Eng Dier's it's only my comfortable alternative for player 1.

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

S.

Il sab 27 ago 2022, 22:07 sverx @.***> ha scritto:

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? 🤔

— Reply to this email directly, view it on GitHub https://github.com/sverx/devkitSMS/issues/36#issuecomment-1229258015, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABZCLIBOIQEZZYWOICKGNC3V3JYRZANCNFSM56LEACJA . You are receiving this because you authored the thread.Message ID: @.***>

sverx commented 2 years ago

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? :thinking:

image

siriokds commented 2 years ago

I was talking about the keys associated to keyboard.

The Player 1 Fire 1 is Left trigger (Fire 1) on Joypad but Ins-Del key on keyboard. I wrote Home key before.

Player 1 Fire 2 is Right trigger (Fire 2) on Joypad but Home-Clr key on keyboard.

If you see a picture of a SC-3000 you see Home-Clr on the left and Ins-Del on the right...

Il dom 28 ago 2022, 13:36 sverx @.***> ha scritto:

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: image] https://user-images.githubusercontent.com/6738932/187072119-f50f8cf3-6682-49d9-a86b-d0ed72732f23.png

— Reply to this email directly, view it on GitHub https://github.com/sverx/devkitSMS/issues/36#issuecomment-1229438529, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABZCLIBX22KZNHAQDYXRCVLV3NFLNANCNFSM56LEACJA . You are receiving this because you authored the thread.Message ID: @.***>

sverx commented 2 years ago

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? :thinking:

siriokds commented 2 years ago

I don't know. You can check the keys mapping through this game manual:

https://segaretro.org/File:Champion_Tennis_SG1000_AU_Manual.pdf

Il lun 29 ago 2022, 08:49 sverx @.***> ha scritto:

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? 🤔

— Reply to this email directly, view it on GitHub https://github.com/sverx/devkitSMS/issues/36#issuecomment-1229850721, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABZCLIA64ARP3ZRVEO3ZKDDV3RMNZANCNFSM56LEACJA . You are receiving this because you authored the thread.Message ID: @.***>

sverx commented 2 years ago

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!