Comments (59)
from devkitsms.
Sure! Send them over! ❤️
from devkitsms.
Sure! Send them over! ❤️
How can I send you my mods?
from devkitsms.
- 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.
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.
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.
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.
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.
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.
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),aYou mean this is needed for any SG-1000 game to make sure they also run on SC-3000? Good to know!
Exactly.
from devkitsms.
Done.
What's next?
from devkitsms.
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.
Done.
What's next?
Cool.
from devkitsms.
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.
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.
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.
from devkitsms.
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.
from devkitsms.
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.
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:
- 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.
- 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.
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.
from devkitsms.
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.
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 likeunsigned 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.
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.
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.
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.
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.
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.
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.
"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.
"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.
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.
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.
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.
from devkitsms.
from devkitsms.
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.
from devkitsms.
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.
from devkitsms.
OK I had swapped left and right keys but now this should work (at least it does in MEKA!)
from devkitsms.
from devkitsms.
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.
from devkitsms.
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? 🤔
from devkitsms.
from devkitsms.
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.
from devkitsms.
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.
from devkitsms.
OK this should fix player 2 left and right trigger too.
from devkitsms.
Whenever you've got some time please confirm this is working fine so that I can push it to the repository.
from devkitsms.
from devkitsms.
Of course I had uploaded the wrong file... 😅
Try this:
from devkitsms.
from devkitsms.
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.
from devkitsms.
Related Issues (20)
- Example project HOT 4
- PSGSetMusicVolumeAttenuation seems not to be working HOT 8
- Can't find sdcc 3.9.5 HOT 4
- SMS_readPaddle() never returns if the paddle is disconnected HOT 5
- Can I use the makesms to convert the file that contains CODE and DATA bank HOT 22
- Interrupt and VDP processing HOT 8
- 32bits variables HOT 2
- Using PSGlib with banked code HOT 4
- Macros to save/restore the bank mapped to slot2? HOT 9
- Ability to install a vblank handler HOT 7
- Need clear vram on startup HOT 3
- Adding examples to this repo HOT 6
- issue with compressed songs spawning multiple banks HOT 3
- New Unsafe and Vertical Orientation Functions HOT 17
- SG/SC -> SG_byte_brief_array_to_VDP_data HOT 1
- SMS_saveROMBank() implementation in SMSLib.h makes it only usable in the same scope as SMS_restoreBank() HOT 9
- PSGLib - Allow to set volume attenuation on SFX HOT 4
- ihx2sms fails with multi-segment static libraries HOT 9
- devkitSMS adopted in z88dk HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from devkitsms.