Jump to content
  • Advertisement
Sign in to follow this  
Boruki

Keys Please

This topic is 4843 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to figure out how to get lower and uppercase without a dodgy if shift +(number) hack stuff. 'A' and 'a' are both the same apparently.. So guys, how did you get it to let you have caps and lower case?

Share this post


Link to post
Share on other sites
Advertisement
In what context are you talking about? Are you asking about how to map key codes into character values from keyboard input? If so, what programming language are you using and what input API?

Share this post


Link to post
Share on other sites
Ugg, sorry.. I'm used to posting stuff under the OpenGL board. It's C++, OpenGL.. currently I use the 'VK_TAB' or 'A' from the wParam in the main loop to register key strokes.

What I'm asking is how to make it so I get uppercase and lowercase keys, currently it all goes to uppercase (A = A and a = a.. but there is no a).

Share this post


Link to post
Share on other sites
clicky for DirectX
The (ugly) code below works for me(win32)


////////////////////////////////////////////////////////////////////
///////////////////////////////////////
// VK2char
// WndProc helping function
// converts the VK to a char
/////////////////////////////////////////////////////////////////////
//////////////////////////////////////

// returns 0 if genesis3d(my current engine) doesn't accept the parameter, returns c if it does
char getAllowedAscii(char c)
{
if( 0x20 <= c )
{
if( c <= 0x7e )
{
return c;
}
}

if( c == 0x08 ) return c; // backspace

return 0;
}

/**
MsVC++ gave some compiler errors and warnings on this piece of code I got
from gamedev.net, probably since
the code was written for DirectInput which gets scancodes. I on the other
hand get virtual key codes.
I fixed them, but I wonder if it a nice fix or a hack fix. I hope it's
the first.
In case anyone wonder here's the url where I got the :
http://www.gamedev.net/reference/programming/features/scan2asc/
**/

static int scan2ascii(DWORD scancode, USHORT* result)
{
WPARAM vk;
static unsigned char State[256];
HKL layout=GetKeyboardLayout(0);


if (GetKeyboardState(State)==FALSE)
return 0;
vk=MapVirtualKeyEx(scancode,1,layout);
return ToAsciiEx(vk,scancode,State,result,0,layout);
}

char VK2char(WPARAM vk)
{
int r;
unsigned short c[2];

if( vk == VK_RETURN ) return '\n';// return key is pressed

vk = MapVirtualKey(vk, 0);
if( vk == 0 ) return 0;

r = scan2ascii( vk, c);

if( r )
{
if( c[0] > 255 ) return 0; // we don't want to use
// characters outside of the char range
return getAllowedAscii( (char) c[0] );
}
return 0;
}





edit: fixed newlines

Share this post


Link to post
Share on other sites
I guess you should test for VK_SHIFT to know the difference between a "A" keystroke that's upper or lower case? I guess its VK_CAPITAL to know if Caps Lock is on.

Hope this helps

Eric

Share this post


Link to post
Share on other sites
Quote:
Original post by Boruki
I'm trying to figure out how to get lower and uppercase without a dodgy if shift +(number) hack stuff.

'A' and 'a' are both the same apparently.. So guys, how did you get it to let you have caps and lower case?

There are essentially three ways to do it. I actually wrote an entry in my blog about this, including a bleeding-edge MMX version of strupr (which converts 8 characters at a time, and is several times faster than other methods).

Share this post


Link to post
Share on other sites
Quote:
I actually wrote an entry in my blog about this, including a bleeding-edge MMX version of strupr (which converts 8 characters at a time, and is several times faster than other methods).

To refresh MMX skillz, had a look at this and it is possible to go a bit faster :)

; setup
movq CONST_Z, [z_1]
movq CONST_A, [a_1]
movq CONST_DELTA, [delta]

; process 8 chars
movq CHARS, [src_chars]
movq Z_MASK, CONST_Z
movq A_MASK, CHARS
pcmpgtb A_MASK, CONST_A
pcmpgtb Z_MASK, CHARS
MASK := A_MASK
pand MASK, Z_MASK
pand MASK, CONST_DELTA
psub CHARS, MASK ; mmx doesn't support load-execute-store arithmetic
movq [dst_chars], CHARS


We need 9 MMX instructions per block instead of 13.
The uppercase symbols are registers and can be allocated as desired. General tip on MMX: put constants in memory, load them before looping and keep in registers. You have 8 - use 'em! :)

Share this post


Link to post
Share on other sites
Quote:
Original post by Jan Wassenberg
To refresh MMX skillz, had a look at this and it is possible to go a bit faster :)
*** Source Snippet Removed ***
We need 9 MMX instructions per block instead of 13.
The uppercase symbols are registers and can be allocated as desired. General tip on MMX: put constants in memory, load them before looping and keep in registers. You have 8 - use 'em! :)

While it's true that you could improve the speed of my code by a few cycles by keeping the masks in spare MMX registers, your code is actually a full 5 cycles slower in the loop than mine, due to poor instruction ordering and the use of movq. movq has 6 cycles of latency, compared to pshufw's 2, which is why I used pshufw in such a contorted way.

Share this post


Link to post
Share on other sites
Oh goody, am refreshing pipeline sim skillz as well :)

Quote:
your code is actually a full 5 cycles slower in the loop than mine, due to poor instruction ordering and the use of movq. movq has 6 cycles of latency, compared to pshufw's 2, which is why I used pshufw in such a contorted way.

A "full" 5 clocks slower? No, sir. First, instructions are reordered automatically according to which of their dependencies completes, so that is not an issue. Oh, you're on a P4, right? My sympathies :P I write for Athlon, where MOVQ is 2 clocks (+2 for L1 access), as it should be :)

So let's look at instruction flow. After incorporating a little trick (prefetch), this runs in 10 clocks:

pcmpgtb A_MASK, CONST_A
movq PREFETCH_CHARS, [next_src_chars] // potential problem: read beyond end of buffer

pcmpgtb Z_MASK, CHARS

nop

pand A_MASK, Z_MASK
movq Z_MASK, CONST_Z

nop

pand A_MASK, CONST_DELTA

nop

psub CHARS, A_MASK; mmx doesn't support load-execute-store arithmetic
movq A_MASK, PREFETCH_CHARS

nop

movq [dst_chars], CHARS
movq CHARS, PREFETCH_CHARS
jmp loop



Your code as written requires 15:

movq mm1, [edx] ; the packed characters

movd mm2, eax // vector decode :(

movd mm3, ebx

nop

movq mm0, mm1
pshufw mm4, mm2, 00000000b ; the lower bounds mask
pshufw mm2, mm2, 01010101b ; the upper bounds mask

pshufw mm3, mm3, 00000000b ; the subtraction mask

pcmpgtb mm1, mm4
pcmpgtb mm2, mm0

nop

pand mm3, mm1

nop

pand mm3, mm2

nop

psubb mm0, mm3

nop

movq [edx], mm0
jmp

Surprisingly, the extra instructions turn out not to really affect performance but of course make interleaving harder. What really ends up hurtin' is MOVD, which is penalized on Athlon (3 clock latency and blocks the pipe).

@OP: sorry for hijacking the thread :)

Share this post


Link to post
Share on other sites
What message are you using?

WM_KEYDOWN tells you what that a key was pressed and tells you which key.

WM_CHAR tells you which character that a pressed key represents - which obviously changes due to localisation issues and keyboard starte (what other keys are held down etc.)




Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!