1. Multi-keyread routine
- Posted by Michael Bolin <michaeltom at GEOCITIES.COM> Jun 10, 1997
- 891 views
- Last edited Jun 11, 1997
Here's an extremely useful library routine for reading the keyboard. It is used just like get_key(), except that it's called get_keys(), it returns a sequence instead of an atom, and the values returned are scan codes, instead of ASCII codes. The advantage is that the routine will recognize multiple keypresses at the same time, and return them in one sequence. Also, there is no repeat delay, instead the code is returned constantly until the key is released. Finally, the routine is also some 10-20 times faster than get_key() Regards, Michael Bolin ------------------------------------ start keyread.e include machine.e atom d_interrupt_ad,e_interrupt_ad procedure disable_interrupts() call(d_interrupt_ad) end procedure procedure enable_interrupts() call(e_interrupt_ad) end procedure d_interrupt_ad=allocate(2) e_interrupt_ad=allocate(2) if d_interrupt_ad<1 or e_interrupt_ad<1 then puts(1,"Could not allocate memory!") abort(1) end if poke(d_interrupt_ad,{#FA,#C3}) -- cli - ret poke(e_interrupt_ad,{#FB,#C3}) -- sti - ret sequence usual_address atom keyboard_address,keyb_point atom code_segment,segment,key_buffer segment=allocate(4) lock_memory(segment,4) key_buffer=allocate(1024) lock_memory(key_buffer,1024) keyb_point=allocate(4) lock_memory(keyb_point,4) poke(keyb_point,{0,0,0,0}) -- offset into keyboard buffer sequence save_segment_code save_segment_code = { #53, -- push ebx #0E, -- push cs or #1E push ds -- only a 16-bit value #5B, -- pop ebx #89, #1D} & int_to_bytes(segment) & -- mov segment, ebx {#5B, -- pop ebx #C3} -- ret atom save_segment save_segment = allocate(length(save_segment_code)) poke(save_segment, save_segment_code) call(save_segment) -- save code segment code_segment = bytes_to_int(peek({segment,4})) poke(save_segment+1, #1E) call(save_segment) -- save data segment usual_address = get_vector(9) sequence keyboard_code keyboard_code={#1E, -- push ds #60, -- pushad #BB} & peek({segment,4}) & -- mov ebx, data segment value {#53, -- push ebx #1F, -- pop ds #BA,#60,00,00,00, -- mov edx,#60 #EC, -- in al,edx #BE} & int_to_bytes(keyb_point) & -- mov esi,keybuffer offset {#8B,#2E} & -- mov ebp,[esi] #BE & int_to_bytes(key_buffer) & -- mov esi,keybuffer {#88,#04,#2E} & -- mov [esi+ebp],al #BE & int_to_bytes(keyb_point) & -- move esi,keybuffer offset {#45, -- inc ebp #81,#E5,255,3,0,0, -- and ebp,255 #89,#2E, -- mov [esi],ebp #E4,#61, -- in al,0x61 #0C,#82, -- or al,0x82 #E6,#61, -- out 0x61,al #24,#7F, -- and al,0x7f #E6,#61, -- out 0x61,al #B0,#20, -- mov al,0x20 #E6,#20, -- out 0x20,al #61, -- popad #1F, -- popds #EA} &int_to_bytes(usual_address[2])& and_bits(usual_address[1],255) & floor(usual_address[1]/256) keyboard_address=allocate(length(keyboard_code)) poke(keyboard_address,keyboard_code) poke(key_buffer,repeat(0,1024)) set_vector(9,{code_segment,keyboard_address}) sequence pressed_keys sequence two_longs,two_codes pressed_keys={} 75,203,80,208,72,200,73,201,71,199,82,210} 28+256,28+384,56+256,56+384,29+256,29+384,333,333+128, 331,331+128,336,336+128,328,328+128,329,329+128,327, 327+128,338,338+128} sequence old_codes old_codes={} global function get_keys() -- Returns a sequence of keys currently pressed sequence codes,slice integer offset,place,key,code,pos disable_interrupts() offset=peek(keyb_point) poke(1052,peek(1050)) -- Clear keyboard buffer if offset=0 then enable_interrupts() return pressed_keys end if poke(keyb_point,0) codes=old_codes & peek({key_buffer,offset}) enable_interrupts() place=1 while place<=length(codes) do code=codes[place] if code=224 then if length(codes)-place=0 then exit -- If not enough codes in buffer end if pos=find(codes[place+1],two_longs) if pos then key=two_codes[pos] place=place+1 else key=0 end if elsif code=225 then -- Ignore pause key key=0 if length(codes)-place>=5 then place=place+4 else exit end if else key=code end if if key then -- Insert or remove key from pressed list if and_bits(key,128)=128 then pos=find(key-128,pressed_keys) if pos then pressed_keys=pressed_keys[1..pos-1] & pressed_keys[pos+1..length(pressed_keys)] end if else pos=find(key,pressed_keys) if pos=0 then pressed_keys=append(pressed_keys,key) end if end if place=place+1 else place=place+2 end if end while old_codes=codes[place..length(codes)] return pressed_keys end function ------------------------------------ end keyread.e
2. Re: Multi-keyread routine
- Posted by Lee woo seob <wslee at HHI.CO.KR> Jun 13, 1997
- 882 views
Dear Bolin... Yes, Your routine must be extremely useful, especially in game program!!!. I will use your routine in my game program now under development, instead of using CTRL, ALT, SHIFT key detection routine. You must post this routine to Euphoria home page, with neat demo program and detail readme.txt. a question: Which value returns, {} or -1, when no key is pressed, in your get_keys()? I think it's better to return -1 in consistent with other routines of Euphoria... Thanks much! from Lee Woo Seob.
3. Re: Multi-keyread routine
- Posted by mark honnor <m.honnor at XTRA.CO.NZ> Jun 13, 1997
- 889 views
Thank you also from Augorian! My games now run faster as they do not have to wait for the get_key() function to actually return a key press!! WoHoo! --Augorian;