Author Topic: A few pushes to the Development build  (Read 14985 times)

0 Members and 1 Guest are viewing this topic.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
A few pushes to the Development build
« on: November 29, 2019, 04:14:56 am »
Over the last several days, I've been doing a little work with pushing changes to QB64, and I wanted to take a moment to just document what's altered so folks can be aware of things.

1) I fixed the issue with $IF UNDEFINED (as described here: https://www.qb64.org/forum/index.php?topic=1910.msg111352#msg111352)

2) I expanded functionality with _PUTIMAGE so it can now be used with the same _SOURCE and _DEST.  Before, it would toss an error for us; now it works with no issue at all.  _PUTIMAGE (100,100)-(200,200), 0, 0, (200,200)-(300,300) will copy a section from the active screen and then paste it somewhere else over that same screen.

3) I replaced our _CONSOLEFONT with a blank stub that does nothing, by default.  The function calls to change the font and font size with the console in Windows requires modern API calls, and won't work with any version of Windows older than Vista.  By enabling the command be default, it means that QB64 would no longer work on Windows XP, Windows 2000, or any versions older than Windows Vista...   I don't think anyone really wants to obsolete older OSes from what we work with, so this command has been replaced with a simple blank stub.

IF you're one of the few people who run a version of Windows Vista, or newer, and who wants to be able to change font and font size in the console, then all you need to do is comment out the stub, uncomment out the working routine, and then run the batch file "purge_libqb_only.bat" so QB64 will automatically rebuild the library to take advantage of the routine you just put back in there.

The framework is there for folks who want to use it, with a simple 1, 2, 3 change, while it keeps us from failing to compile and run on older Windows machines.  ;)

https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: A few pushes to the Development build
« Reply #1 on: December 04, 2019, 01:05:53 pm »
Pushed an option into the IDE today so you can toggle to Ignore Warnings on and off.   (Variable not defined, or CONST name already in use warnings.)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline RhoSigma

  • QB64 Developer
  • Forum Resident
  • Posts: 565
    • View Profile
Re: A few pushes to the Development build
« Reply #2 on: December 04, 2019, 01:09:44 pm »
Funny, an "anti OPTION _EXPLICIT" switch, I like it :)
My Projects:   https://qb64forum.alephc.xyz/index.php?topic=809
GuiTools - A graphic UI framework (can do multiple UI forms/windows in one program)
Libraries - ImageProcess, StringBuffers (virt. files), MD5/SHA2-Hash, LZW etc.
Bonus - Blankers, QB64/Notepad++ setup pack

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: A few pushes to the Development build
« Reply #3 on: December 04, 2019, 01:18:01 pm »
Funny, an "anti OPTION _EXPLICIT" switch, I like it :)

We’re trying to get everything ready for the next stable release of QB64, and this is one of the features that “Steve’s Repo” has that I definitely wanted to get into QB64 by the next release.  ;D
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline RhoSigma

  • QB64 Developer
  • Forum Resident
  • Posts: 565
    • View Profile
Re: A few pushes to the Development build
« Reply #4 on: December 04, 2019, 01:47:58 pm »
We’re trying to get everything ready for the next stable release of QB64, and this is one of the features that “Steve’s Repo” has that I definitely wanted to get into QB64 by the next release.  ;D

Well, then I've something to look at too for the next stable release. After the run with the BIN$ function in the other place, I did also try the reverse part and found some missings for &B prefixed number strings.

We can use it in regular formulas (3 + &B1101 etc.), this is already handled by qb64.bas and is there since SDL days. We can also use it as VAL(&B0101) now, but whoever made the VAL addition overlooked some other uses.

INPUT a& => does accept &H, &O but not &B => see libqb.cpp function hexoct2uint64()

INPUT #fid, a& => does read &H, &O but not &B => see libqb.cpp function n_inputnumberfromfile()

DATA => does read &H, &O but not &B => see libqb.cpp function n_inputnumberfromdata()

FOR i% = 1 TO 3
    READ a&
    PRINT a&
NEXT i%
END
DATA &Hff,&O377,&B11111111

And by a quick search for "oct" it appeared, there are several more functions which have the hex/oct conversion in it but not the bin conversion. Maybe It would be a good idea to see if all these code redundancies can be pulled together in one conversion routine, which then can be called from the appropriate places.
My Projects:   https://qb64forum.alephc.xyz/index.php?topic=809
GuiTools - A graphic UI framework (can do multiple UI forms/windows in one program)
Libraries - ImageProcess, StringBuffers (virt. files), MD5/SHA2-Hash, LZW etc.
Bonus - Blankers, QB64/Notepad++ setup pack

Offline hanness

  • Forum Regular
  • Posts: 210
    • View Profile
Re: A few pushes to the Development build
« Reply #5 on: December 05, 2019, 12:52:28 pm »
Here is my list of items I'd love to still see addressed prior to the release of the next stable release:

Issue #1: SLEEP command with a specified sleep time does not work in console.

Sample code:

NOTE: Run the code below twice:

First Run: Run it as is and note that the sleep command works fine.

Second Run: Uncomment the lines that are currently commented out to run the program in a console. Note that the program will never advance past the sleep command until a key is pressed.


---------------------------------------
' $CONSOLE:ONLY
' _DEST _CONSOLE: _SOURCE _CONSOLE

PRINT "If the SLEEP command is working, then the program should continue"
PRINT "in 5 seconds without any need to press a key...."
PRINT
SLEEP 5
PRINT "If we arrive here <without pressing a key> then SLEEP is working,"
PRINT "otherwise it is not working."
---------------------------------------

Issue #2: Whether due to changes made by Microsoft or whatever reason, many of the $VERSIONINFO items are not working.

Sample code:

---------------------------------------
$VERSIONINFO:CompanyName=My Company
$VERSIONINFO:FILEVERSION#=1,2,3,4
$VERSIONINFO:ProductName=My QB64 App
$VERSIONINFO:LegalCopyright=(c) 2019 by My Company
---------------------------------------

Of the above items, the only one that will display the information specified is "FILEVERSION". There may well be others that also don't work, the above is only a sampling, not an all inclusive list.

Issue #3: I know that the built-in help may not be finalized until the next release is finalized, but I thought that I would simply note that I'm not seeing help for the following items as yet. There may be others, but these are just the ones I tried to lookup and was unable to locate:

_consoleinput
_cinp
_consolefont


Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: A few pushes to the Development build
« Reply #6 on: December 05, 2019, 03:33:35 pm »
Here is my list of items I'd love to still see addressed prior to the release of the next stable release:

Issue #1: SLEEP command with a specified sleep time does not work in console.

Sample code:

NOTE: Run the code below twice:

First Run: Run it as is and note that the sleep command works fine.

Second Run: Uncomment the lines that are currently commented out to run the program in a console. Note that the program will never advance past the sleep command until a key is pressed.


---------------------------------------
' $CONSOLE:ONLY
' _DEST _CONSOLE: _SOURCE _CONSOLE

PRINT "If the SLEEP command is working, then the program should continue"
PRINT "in 5 seconds without any need to press a key...."
PRINT
SLEEP 5
PRINT "If we arrive here <without pressing a key> then SLEEP is working,"
PRINT "otherwise it is not working."
---------------------------------------

I just spent all afternoon looking at this, only to come to a fateful, irrefutable conclusion:  It's simply not going to happen.

To get information from the console, we use the windows ReadConsoleInputA function.  Unlike INKEY$ or _KEYHIT, this function doesn't return blank values to us.  It sits there, patiently waiting, until an user event occurs -- mouse movement, keyboard event, or other such thing.

Think of it as basically the equivalent of this:

Code: [Select]
PRINT "TimeStart:"; TIME$
FakeSleep 2
PRINT "TimeStop :"; TIME$

SUB FakeSleep (Time AS _FLOAT)
    DIM ExitTime AS _FLOAT
    ExitTime = TIMER + Time
    DO
        a$ = INPUT$(1)
        PRINT "Time in Loop: "; TIMER - ExitTime
    LOOP UNTIL TIMER > ExitTime
END SUB

The program pauses execution until an event occurs, so it can't just loop back and forth to check the start time against a finish time, and then exit. 

You *have to cause an event* to make it exit the input routine, before you can check the time -- and, if you cause a keyboard event to make it exit the input routine, you're going to exit the sleep routine anyway!

SLEEP used to not work at all for us with the console.  With the changes made to it, it now works, but there's no way the optional TIME counter is going to work with it.  Unless someone can find a way to read from the console, without pausing program execution while waiting for an input event, there's just no way SLEEP is going to work with a timer like that.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: A few pushes to the Development build
« Reply #7 on: December 05, 2019, 03:42:26 pm »
I haven't worked with API stuff in 6+ months, but is this along the lines you would need?

https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-settimer

https://docs.microsoft.com/en-us/windows/win32/winmsg/using-timers

In other words, could that timer API function be turned into a _SLEEPCONSOLE command?

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: A few pushes to the Development build
« Reply #8 on: December 05, 2019, 03:52:05 pm »
It's not a matter of setting a timer; it's a matter of ReadConsoleInput not responding until an event occurs. 

It's a lot like INPUT is in QB64 -- no matter what time event you have going, once the program hits INPUT, it pauses until that input event is over.

SLEEP is a "Pause until a key is hit" type routine, and with the console, ReadConsoleInput is a command that "pauses everything until an input event occurs." 

If we exit ReadConsoleInput, we're going to exit SLEEP as well.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: A few pushes to the Development build
« Reply #9 on: December 05, 2019, 05:16:55 pm »
Well then that would mean re-writing a flow-through routine to replace ReadConsoleInput. That seems like a handful. I recall when I was writing some C programs much earlier in the year, I had to keep dodging statements that would pause for input. Well, good luck with it, but if it helps, I'm in agreement that it doesn't appear to be worth the trouble, and certainly is not a priority.

Thanks,

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline hanness

  • Forum Regular
  • Posts: 210
    • View Profile
Re: A few pushes to the Development build
« Reply #10 on: December 05, 2019, 09:09:29 pm »
Thanks greatly for looking into this. I can certainly accept the limitations noted. You may just want to put a note in the help for sleep to that effect.

Thanks again for looking into it.




Offline Ed Davis

  • Newbie
  • Posts: 40
    • View Profile
Re: A few pushes to the Development build
« Reply #11 on: December 05, 2019, 09:16:59 pm »
It's not a matter of setting a timer; it's a matter of ReadConsoleInput not responding until an event occurs. 

It's a lot like INPUT is in QB64 -- no matter what time event you have going, once the program hits INPUT, it pauses until that input event is over.

SLEEP is a "Pause until a key is hit" type routine, and with the console, ReadConsoleInput is a command that "pauses everything until an input event occurs." 

If we exit ReadConsoleInput, we're going to exit SLEEP as well.

I had the same problem (needing a non-blocking ReadConsoleInput()) in a Console program I was writing.  The solutions was the WaitForSingleObject() function.  For instance:

Code: [Select]
// con_in is a handle to the console input buffer
// wait is the maximum number of milliseconds to wait for a key, mouse or other input event
if (WaitForSingleObject(con_in, wait) == WAIT_OBJECT_0) {
  // there is data, read it - could be keyboard, mouse or other console events
} else {
  // no events on con_in, or the wait period expired, go do something else for a while
}

There are various other returns from WaitForSingleObject().  See the Win32 documentation for details.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: A few pushes to the Development build
« Reply #12 on: December 05, 2019, 09:30:37 pm »
I had the same problem (needing a non-blocking ReadConsoleInput()) in a Console program I was writing.  The solutions was the WaitForSingleObject() function.  For instance:

Code: [Select]
// con_in is a handle to the console input buffer
// wait is the maximum number of milliseconds to wait for a key, mouse or other input event
if (WaitForSingleObject(con_in, wait) == WAIT_OBJECT_0) {
  // there is data, read it - could be keyboard, mouse or other console events
} else {
  // no events on con_in, or the wait period expired, go do something else for a while
}

There are various other returns from WaitForSingleObject().  See the Win32 documentation for details.

I’ll definitely check into this.  Many thanks for bringing it to my attention!
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: A few pushes to the Development build
« Reply #13 on: December 06, 2019, 10:22:37 am »
With Ed's advice and some experimention of my own, I think I've sorted out the issue with SLEEP in the console not working with any timer.

Before I push any changes into the repo, I'd appreciate it if a few people with the latest development build would give these changes a test run.

Steps for testing:
1) Have the latest Dev build.
2) In internal/c, rename libqb.cpp to libqb.bak to back up the original file, if you want to.
3) Download the libqb.cpp below.
4) Paste it into internal/c.
5) Run the purge_libqb_only.bat file so QB64 will rebuild its needed library automatically.

Now, feel free to run QB64.exe and test all sorts of things out with SLEEP in the console.

A simple test to see if it times out around the time we'd expect:
Code: [Select]
$CONSOLE:ONLY
_DEST _CONSOLE: _SOURCE _CONSOLE

PRINT "Foo"

t# = TIMER
SLEEP 2
PRINT USING "##.### seconds"; TIMER - t#

A simple test to see if it still works without a timer:
Code: [Select]
$CONSOLE:ONLY
_DEST _CONSOLE: _SOURCE _CONSOLE

PRINT "Foo"

SLEEP

The code which pertains to all this working for us, is this: 
Code: C++: [Select]
  1.         #ifdef QB64_WINDOWS
  2.  
  3.             if (read_page->console){
  4.                 int32 junk=0,junk2=0;
  5.                 DWORD dwRet;
  6.                 HANDLE hStdin = GetStdHandle (STD_INPUT_HANDLE);
  7.                 FlushConsoleInputBuffer(hStdin);
  8.                 if (passed){
  9.                             do{
  10.                                 now=GetTicks();
  11.                                 if (now<prev)return;//value looped?
  12.                                 elapsed=now-prev;//elapsed time since prev
  13.                                 ms = ms-elapsed;
  14.                                 prev=now;
  15.                                 dwRet = WaitForSingleObject(hStdin,ms); //this should provide our pause
  16.                                 if (dwRet==WAIT_TIMEOUT)return; //and if we timeout without any input, we exit early.
  17.                                 if (dwRet==WAIT_OBJECT_0){//this says the console had input
  18.                                     junk=func__getconsoleinput();
  19.                                     if(junk==1){//this is a valid keyboard event.  Let's exit SLEEP in the console.
  20.                                         Sleep(100);//Give the user time to remove their finger from the key, before clearing the buffer.
  21.                                         FlushConsoleInputBuffer(hStdin);//flush the keyboard buffer after, so we don't leave stray events to be processed (such as key up events).
  22.                                         return;
  23.                                     }else{//we had an input event such as the mouse.  Ignore it and clear the buffer so we don't keep responding to mouse inputs
  24.                                         FlushConsoleInputBuffer(hStdin);
  25.                                     }
  26.                                 }
  27.                             }while(ms>0);//as long as our timer hasn't expired, we continue to run the loop and countdown the time remaining
  28.                             return; //if we get here, something odd happened.  We should expire automatically with the WAIT_TIMEOUT event before this occurs.
  29.                 }
  30.                 do{ //ignore all console input unless it's a keydown event
  31.                     junk=func__getconsoleinput();
  32.                 }while(junk!=1); //only when junk = 1 do we have a keyboard event
  33.                 Sleep(100); //Give the user time to remove their finger from the key, before clearing the buffer.
  34.                 FlushConsoleInputBuffer(hStdin); //and flush the keyboard buffer after, so we don't leave stray events to be processed.
  35.             }
  36.         #endif

Notice how it flushes the console input buffers after we exit SLEEP -- this is intention and not a bug/glitch.  If we don't clear those buffers, the KEY UP event will remain in them and carry over to the next read of our code, causing us issues.

For now, I've automatically set a delay of 1/10th of a second for someone to lift their finger off the key after pressing it down, and that seems more than sufficient from testing on my machine.  If you run the code on your PC, and it instantly goes to SYSTEM instead of "PRESS <ANY KEY> TO END", at the end of the two sample codes above, speak up and I can up that delay a bit more.

_KEYCLEAR has also been fixed so that it now also clears the console input buffer for us, so IF you end up going straight to system with the console program closing as soon as you press a key, you can always try to add a manual delay and flush that buffer so it won't carry over, such as:

Code: [Select]
SLEEP
_DELAY .2 //time to lift the finger off the key we hit
_KEYCLEAR //and then clear the buffer
END //so the up key doesn't break the END event.



Test it out, report results, and if all goes well, I'll push the changes into the repo and SLEEP will now work inside the windows console with a timed event.  (As well as adding functionality so that _KEYCLEAR will now work to clear the console buffer also.)

« Last Edit: December 06, 2019, 10:49:20 am by SMcNeill »
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline hanness

  • Forum Regular
  • Posts: 210
    • View Profile
Re: A few pushes to the Development build
« Reply #14 on: December 06, 2019, 02:49:08 pm »
Using your first sample code there is a problem. To best illustrate, I'm adding a single line of code at the end so that you end up with this:


$CONSOLE:ONLY
_DEST _CONSOLE: _SOURCE _CONSOLE

PRINT "Foo"

t# = TIMER
SLEEP 2
PRINT USING "##.### seconds"; TIMER - t#
INPUT "Enter some text: ", Text$


If allowed to run with no user input, it runs just fine. However, if you press a key during the 2 second pause the program advances as expected without waiting for the 2 seconds, but when it reaches the input statement note that as you try to type you see no characters displayed. You have to press ENTER twice to get past the input statement.

I experience the same problem with the second sample where I again add the input statement:

$CONSOLE:ONLY
_DEST _CONSOLE: _SOURCE _CONSOLE

PRINT "Foo"

SLEEP
INPUT "Enter some text: ", Text$