Author Topic: INP addresses?  (Read 4418 times)

0 Members and 1 Guest are viewing this topic.

Offline Omerta7486

  • Newbie
  • Posts: 33
  • √𝜋²
    • View Profile
INP addresses?
« on: September 01, 2018, 07:14:51 pm »
Does anyone know of any good documentation on the INP memory addresses? The only one I can figure out is the &H60 address for keyboard input...

Thanks in advance,

-Omerta
The knowledge that's seeking the favor of another means the murder of self.

Latest version of my game, here  Omertris: Invasion

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: INP addresses?
« Reply #1 on: September 01, 2018, 08:25:13 pm »
Hi Omerta
here some links
http://qb64.org/wiki/INP
https://en.wikipedia.org/wiki/Input/output_base_address#Common_I.2FO_base_address_device_assignments_in_IBM_PC_compatible_computers
http://www.o-bizz.de/qbtuts/mallard/sbfaq.htm
http://www.os2site.com/sw/info/memory/ports.txt
but why do you like use INP?  Often there is something that already works on hardware that you want manage at low level.
IMHO be careful to use INP to change hardware settings.
Programming isn't difficult, only it's  consuming time and coffee

FellippeHeitor

  • Guest
Re: INP addresses?
« Reply #2 on: September 02, 2018, 03:52:02 pm »
INP is emulated. Here's the implementation in libqb.cpp:

Code: QB64: [Select]
  1. int32 func_inp(int32 port){
  2.     static int32 value;
  3.     unsupported_port_accessed=0;
  4.     if ((port>65535)||(port<-65536)){
  5.         error(6); return 0;//Overflow
  6.     }
  7.     port&=0xFFFF;
  8.    
  9.     if (port==0x3C9){//read palette
  10.         if (write_page->pal){//avoid NULL pointer
  11.             //convert 0-255 value to 0-63 value
  12.             if (H3C9_read_next==0){//red
  13.                 value=qbr_double_to_long((((double)((write_page->pal[H3C7_palette_register_read_index]>>16)&255))/3.984376-0.4999999f));
  14.             }
  15.             if (H3C9_read_next==1){//green
  16.                 value=qbr_double_to_long((((double)((write_page->pal[H3C7_palette_register_read_index]>>8)&255))/3.984376-0.4999999f));
  17.             }
  18.             if (H3C9_read_next==2){//blue
  19.                 value=qbr_double_to_long((((double)(write_page->pal[H3C7_palette_register_read_index]&255))/3.984376-0.4999999f));
  20.             }
  21.             H3C9_read_next=H3C9_read_next+1;
  22.             if (H3C9_read_next==3){
  23.                 H3C9_read_next=0;
  24.                 H3C7_palette_register_read_index=H3C7_palette_register_read_index+1;
  25.                 H3C7_palette_register_read_index&=0xFF;
  26.             }
  27.             return value;
  28.         }//->pal
  29.         return 0;//non-palette modes
  30.     }
  31.    
  32.     /*
  33.        3dAh (R):  Input Status #1 Register
  34.         bit   0  Either Vertical or Horizontal Retrace active if set
  35.        1  Light Pen has triggered if set
  36.        2  Light Pen switch is open if set
  37.        3  Vertical Retrace in progress if set
  38.        4-5  Shows two of the 6 color outputs, depending on 3C0h index 12h.
  39.         Attr: Bit 4-5:   Out bit 4  Out bit 5
  40.        0          Blue       Red
  41.        1        I Blue       Green
  42.        2        I Red      I Green
  43.     */
  44.     if (port==0x3DA){
  45.         value=0;
  46.         if (vertical_retrace_happened||vertical_retrace_in_progress){
  47.             vertical_retrace_happened=0;
  48.             value|=8;
  49.         }
  50.         return value;
  51.     }
  52.    
  53.     if (port==0x60){
  54.         //return last scancode event
  55.         if (port60h_events){
  56.             value=port60h_event[0];
  57.             if (port60h_events>1) memmove(port60h_event,port60h_event+1,255);
  58.             port60h_events--;
  59.             return value;
  60.             }else{
  61.             return port60h_event[0];
  62.         }
  63.        
  64.     }
  65.    
  66.    
  67.    
  68.     unsupported_port_accessed=1;
  69.     return 0;//unknown port!
  70. }
  71.  

From which we get the following ports being currently emulated/supported:

  • 0x3C9 for reading palette data in palette-enabled screen modes
  • 0x3DA for vertical retracing
  • 0x60 for the last keyboard scancode

Any other ports are ignored and return 0.
« Last Edit: September 02, 2018, 03:54:32 pm by FellippeHeitor »

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: INP addresses?
« Reply #3 on: September 02, 2018, 04:58:55 pm »
Thanks Fellippe

So, we can say that inQB64 a set of QBasic functions is emulated!
Because it is not possible to really do in actual OS I can imagine.
Basic and ASM are not in competition! So C++ and ASM! In fact they work at different level.
Moreover some Basic let us to write asm inline (TurboBasic, PowerBasic, FreeBasic...) but not QBasic or QuickBasic !
Surely to use some device there are others Keyword of QB64, while to write a driver for a device we can agree that QB64 (like Qbasic and QuickBasic) is not the right development tool.  ;-)
Programming isn't difficult, only it's  consuming time and coffee

FellippeHeitor

  • Guest
Re: INP addresses?
« Reply #4 on: September 02, 2018, 05:14:36 pm »
...to write a driver for a device we can agree that QB64 (like Qbasic and QuickBasic) is not the right development tool.  ;-)

Exactly!

Offline Omerta7486

  • Newbie
  • Posts: 33
  • √𝜋²
    • View Profile
Re: INP addresses?
« Reply #5 on: September 06, 2018, 02:45:14 pm »
Can we not poll address &H201(Gamepad) ourselves? The gamepad, and the frame buffer/screen buffer are the two addresses I am most interested in.

The first, I want to see if I can separate XInput's Axis 3 for the Xbox/XInput controller's L/R triggers. The second, I want to see if I can squeeze an image into the screen's buffer before it refreshes to help ease the screen tearing inherent to QB64.
The knowledge that's seeking the favor of another means the murder of self.

Latest version of my game, here  Omertris: Invasion

FellippeHeitor

  • Guest
Re: INP addresses?
« Reply #6 on: September 06, 2018, 02:55:06 pm »
I recommend using the _DEVICES interface (and related functions) for your controller. Or even legacy STICK (http://qb64.org/wiki/STICK) which has been adapted to poll controllers via modern approaches as well.

I also recommend using _DISPLAY to stop screen tearing.

Not being able to poll some addresses doesn't mean you can't do what used to be done via interrupts back in DOS days. You just need a more QB64 approach to it.

Offline TerryRitchie

  • Seasoned Forum Regular
  • Posts: 495
  • Semper Fidelis
    • View Profile
Re: INP addresses?
« Reply #7 on: September 06, 2018, 03:11:10 pm »
INP was emulated to allow existing Qbasic code to operate in the QB64 environment. Those INP routines were used in Qbasic to overcome shortcomings in the language. QB64 has all the tools you will ever need for joystick, mouse, palette control, vertical retrace, etc..

The Wiki is a great source for all the commands available:

http://qb64.org/wiki/Keyword_Reference_-_By_usage
In order to understand recursion, one must first understand recursion.

Offline Omerta7486

  • Newbie
  • Posts: 33
  • √𝜋²
    • View Profile
Re: INP addresses?
« Reply #8 on: September 06, 2018, 06:19:55 pm »
The thing with the normal _AXIS() function is that with an XInput device, such as a PC's USB gamepad, or an Xbox 360 controller, the third axis corresponds to the L/R trigger. The problem is that L is on the positive axis and R is on the negative. If both triggers are pulled together, it nulls out to it's neutral state, and it's as if neither trigger had ever been pulled.

Here are some data that I calculated:
Code: QB64: [Select]
  1. XInput Axis 3:
  2. Neutral=-.0000152587890625
  3. L Trigger Max=.996124267578125
  4. L Trigger States=255
  5. L trigger Step=.00390625 +-.000000005
  6. R Trigger Max=-.9960936903953552
  7. R Trigger States=255
  8. R Trigger Step=-.00390625 +-.000000005
  9.  

As you can see, for every step that you pull both triggers together the axis cancels itself out. This is normally not a problem as it's easy to tell if both triggers are being pulled part way, as a human could never perfectly half pull two triggers with the exact same force at the exact same moment. The problem arises when both triggers are pulled all the way, they cancel back out to the axis' neutral state, which tells the program the triggers aren't even being pulled. I was thinking if I could poll the gamepad directly, I may be able to sort the two apart.

I mean, I could build my games around not using both triggers simultaneously, but... If I can't solve such a tedious problem, how can I be a game developer? ;D LOL

[EDIT:] Random thought, but can we use &H3DA to only update our screens between vertical retraces? _DISPLAY and hardware images only gets rid of so much screen tearing.
« Last Edit: September 06, 2018, 06:29:12 pm by Omerta7486 »
The knowledge that's seeking the favor of another means the murder of self.

Latest version of my game, here  Omertris: Invasion