Author Topic: &H colors dont work as CONST  (Read 3112 times)

0 Members and 1 Guest are viewing this topic.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: &H colors dont work as CONST
« Reply #30 on: March 05, 2022, 11:43:51 am »
sOK @Cobalt

I was probably over reacting to:
Quote
I don't really care one way or the other, works fine for me now.

I dislike when I go to use an old program that worked and find out it doesn't... with 2.0+ I do expect old functions have to be checked, never expected to have to recheck Const's too, since 1.4 I think. But now it's on my bug checklist. I remember Qwerkey had a time of it with Consts in his Pi in the Sky program, after that Const were fixed better but still a few things get by. Anyway, live and learn...

Offline _vince

  • Seasoned Forum Regular
  • Posts: 422
Re: &H colors dont work as CONST
« Reply #31 on: March 05, 2022, 09:10:28 pm »
(Unless you're working with a 256 color screen, in which case you'd probably want the include to set the palette to match the names for any temp/secondary screens you might create.)

oh yeah I spent hours wondering why my screen wasn't BananaMania then I realized I was in 256 mode!

anyways, since 256 mode is effectively emulated, why would anyone use that mode?  Why not stick to 32 bit color mode and just create DIM a(256): a(0)=BananaMania: a(1)=_rgb(255,0,0): etc, or have it match the original VGA palette, or map it to 'Hue', or whatever and use that with any graphics command for an effective 256 mode emulation, ie CIRCLE (100,100),3,a(155) instead of CIRCLE (100,100),3,155

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • Steve’s QB64 Archive Forum
Re: &H colors dont work as CONST
« Reply #32 on: March 05, 2022, 10:21:43 pm »
Only real reason for 256 color mode that I can think of is for smaller image file sizes.  A 256 color image has to store the palette (3 or 4 bytes if alpha is included, for 256 colors), and then a single byte for each color pixel.   32-bit colors are 4 bytes per pixel, so quite a bit larger sizes.

Of course, since QB64 currently doesn't support 256 color images with _LOADIMAGE, (it auto coverts them to 32-bit images instead,) and since modern OSes have so much memory available anyway, I don't really see the point for 256 color screens anymore.  Apparently nobody else does either, as we never see posts complaining about not being able to load 256 color images.

I truly think everyone has moved on to 32-bit screens nowadays.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • Steve’s QB64 Archive Forum
Re: &H colors dont work as CONST
« Reply #33 on: March 06, 2022, 02:05:53 am »
Back to the glitch at hand here:

It appears to me that CONST only deals with 3 values when it comes to explicitly defining a type -- float, string, and integer64.  Down in QB64.bas, around line 2250, we find the following for storing values in a const:

Code: QB64: [Select]
  1.                                 If t And ISFLOAT Then
  2.                                     constval## = _CV(_Float, e$)
  3.                                     constval&& = constval##
  4.                                     constval~&& = constval&&
  5.                                 Else
  6.                                     If (t And ISUNSIGNED) And (t And 511) = 64 Then
  7.                                         constval~&& = _CV(_Unsigned _Integer64, e$)
  8.                                         constval&& = constval~&&
  9.                                         constval## = constval&&
  10.                                     Else
  11.                                         constval&& = _CV(_Integer64, e$)
  12.                                         constval## = constval&&
  13.                                         constval~&& = constval&&
  14.                                     End If
  15.                                 End If

Right after that, we find the following little snippet of code:
Code: QB64: [Select]
  1.                                 'override type?
  2.                                 If typeoverride Then
  3.                                     'range check required here (noted in todo)
  4.                                     t = typeoverride
  5.                                 End If

Which, as the comment above, seems as if it's just a stub for code that was intended to be added later.  There's supposed to be a range check in that IF block, but it's not there.  It's just a note in some forgotten todo list somewhere.  :P

The math evaluator works with the formula foo = &HFF848888~& to make that &H the proper unsigned long value, but the CONST evaluator doesn't have a range check to make CONST foo~& an unsigned long.  It's trying to store the value as an _CV(_integer64) value.

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

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • Steve’s QB64 Archive Forum
Re: &H colors dont work as CONST
« Reply #34 on: March 06, 2022, 02:49:03 am »
I'm thinking the simplest fix for this is to go in around line 2350 (do a search for the label "constAddDone:"), where you'll find this:

Code: QB64: [Select]
  1.                             constdefined(i2) = 1
  2.                             constcname(i2) = n$
  3.                             constnamesymbol(i2) = typevalue2symbol$(t)
  4.                             If Error_Happened Then GoTo errmes
  5.                             consttype(i2) = t
  6.                             If t And ISSTRING Then
  7.                                 conststring(i2) = e$
  8.                             Else
  9.                                 If t And ISFLOAT Then
  10.                                     constfloat(i2) = constval##
  11.                                 Else
  12.                                     If t And ISUNSIGNED Then
  13.                                         constuinteger(i2) = constval~&&
  14.                                     Else
  15.                                         constinteger(i2) = constval&&
  16.                                     End If
  17.                                 End If
  18.                             End If
  19.  
  20.                             constAddDone:

Add in a few simple lines to check scope and we make certain that our value is what we intend for it to be, like so:
Code: QB64: [Select]
  1.                             constdefined(i2) = 1
  2.                             constcname(i2) = n$
  3.                             constnamesymbol(i2) = typevalue2symbol$(t)
  4.                             If Error_Happened Then GoTo errmes
  5.                             consttype(i2) = t
  6.                             If t And ISSTRING Then
  7.                                 conststring(i2) = e$
  8.                             Else
  9.                                 If t And ISFLOAT Then
  10.                                     constfloat(i2) = constval##
  11.                                 Else
  12.                                     If t And ISUNSIGNED Then
  13.                                         If t And 8 Then constval~&& = constval~&& Mod (2 ^ 8) 'unsigned byte
  14.                                         If t And 16 Then constval~&& = constval~&& Mod (2 ^ 16) 'unsigned integer
  15.                                         If t And 32 Then constval~&& = constval~&& Mod (2 ^ 32) 'unsigned long
  16.                                         constuinteger(i2) = constval~&&
  17.                                     Else
  18.                                         If t And 8 Then constval&& = constval&& Mod (2 ^ 8) 'signed byte
  19.                                         If t And 16 Then constval&& = constval&& Mod (2 ^ 16) 'signed integer
  20.                                         If t And 32 Then constval&& = constval&& Mod (2 ^ 32) 'signed long
  21.                                         constinteger(i2) = constval&&
  22.                                     End If
  23.                                 End If
  24.                             End If
  25.  
  26.                             constAddDone:

CONST only holds floats, strings, and int64 values.  We have to make certain that we store what we want properly, rather than just let it toss the value into the largest container that it can fit.

-1 as a byte is: &HFF
-1 as an integer is: &HFFFF
-1 as a long is:&HFFFFFFFF
-1 as an integer64 is: &HFFFFFFFFFFFFFFFF

Same number, but much different results when we store it in different variable types.



There's probably other ways and other places to fix this issue along the way of generating our value/type, but this seems like it'd be about the simplest and easiest to do for us, to me. 

Feel free to grab the file below, compile it, and test it out, if you want.  I'm thinking it should fix this issue for good, without breaking anything else.  Give it a few days for folks to try it and and make certain that it works as advertised, and then I'll try and sort out what's required to push it into the repo for everyone, as it's been ages since I last actually pushed a change into the source for us.  I wonder if I can still dig up my Git/Github account  info, or if I'm going to have to go through all that "last credential" hassle to get back into it.  LOL!
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • Steve’s QB64 Archive Forum
Re: &H colors dont work as CONST
« Reply #35 on: March 06, 2022, 11:19:25 am »
@bplus I've finally wrapped my head around what exactly is going on to cause the issue you posted on.

First, let's take a look at the core of the problem:
Code: QB64: [Select]
  1. Const foo~& = -1
  2. Print foo, "foo"
  3. Print 4294967295, "literal"
  4. If foo = 4294967295 Then Print "It matches" Else Print "No match"

Now here, we specify that foo should be an unsigned long, and it's value should be the equivalent of a -1.  We'd expect to see a value of &HFFFFFFFF, overflowed to become 4294967295 for us, and the PRINT statement confirms this value for us.

Unfortunately, the IF statement doesn't think the two numbers match at all!

WHY??

Because QB64 only stores CONST values as one of 4 actual types:  String, Float, Signed Integer64, Unsigned Integer64. 

Sure, we specified that we wanted to store the value as an unsigned value, but CONST only has unsigned integer64's which it stores the numbers as, so that -1 ends up becoming &HFFFFFFFFFFFFFFFF rather than &HFFFFFFFF -- as illustrated below:

Code: QB64: [Select]
  1. Const foo~& = -1
  2. Print foo, "foo"
  3. Print 4294967295, "literal"
  4. If foo = 4294967295 Then Print "It matches" Else Print "No match"
  5.  
  6. UInt64_Max = -1
  7. If foo = UInt64_Max Then Print "It matches" Else Print "No match"

There's no point in specifying CONSTs as byte, integer, or longs.  They'll all simply be integer64s.

The only really interesting and odd thing about these CONST values -- we set a flag to try and keep track of what type they're supposed to be, and PRINT and HEX$ and a few other places make use of that flag to give us the results we expect to see...  It's just that IF and DO and WHILE and such don't bother with that flag, so they don't convert that value.

PRINT foo will print the desired unsigned long value, as it uses that (uint32) flag.
IF foo doesn't use that flag, so it uses the internal unsigned integer64 value...

And that's the basic crux of the issue at hand here.

CONST skyC~& = &HFF8B8888   <-- &H math gives us a negative value for this.
skyC~& is an unsigned integer64 internally, with a flag which is supposed to track its type.
PRINT will use that flag and print the expected type value.
IF doesn't use that flag and thus the 64-bit number doesn't match the expected 32-bit equivalent. 

The code I posted above should fix the issue as far as CONST is concerned, but with &H changing from integer to long to integer64 as it wishes, it's a situation where you could run into just about anywhere.

My suggestion from now on:  If you use &H, specify the return type manually yourself.  Instead of &HFF8B8888, make it &HFF8B8888~&.  This will force that return value to be an unsigned long, rather than a signed long, and that'd stop the issue before it ever started.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: &H colors dont work as CONST
« Reply #36 on: March 06, 2022, 11:40:17 am »
Wow @SMcNeill  what an investigation, I think you love a good coding mystery and from what I can gather from what you described, this one's a beauty of a mess-tery.

When you get into bit stuff you lose me, I am of the humble and probably singular opinion that only -&H.... (minus &H... ) should be negative to be consistent with numbers of any base and not with computer science geeks for the obvious and plain reason: it's obvious and plainly < 0!

Fellippe's proposed upcoming change to Const's still might not help us with &H numbers or will it?

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • Steve’s QB64 Archive Forum
Re: &H colors dont work as CONST
« Reply #37 on: March 06, 2022, 12:02:16 pm »
Fellippe's proposed upcoming change to Const's still might not help us with &H numbers or will it?

It won't as the issue is we're changing counting systems based on the length of the hex after the &H.

&H with up to 4 letters after is counted as an integer
&H with up to 8 letters after is counted as an long.
&H with more than 8 letters is counted as an integer64.

This means that it's literally impossible to represent the numbers from 32768 to 65535 with &H.  (Without specifying a manual data type extension.)

&H7FFE is 32766.
&H7FFF is 32767.
&H8000 is -32768.
&H8001 is -32767.
&H8002 is -32766.

our four digit numbers are signed integers, up until we get up to &HFFFF. which represents -1.  Then, when we add 1 to the value, we get:
&H10000 is 65536.

You can't represent the numbers from 32768 to 65535 with &H.  4 digit &H values are signed integers.  5-8 digit values are signed longs that pick up past the integer cutoff.  (And you have the same issue with values between signed long and where 9 digit integer64 values come from as well.)

Overhauling CONST to make it static variables isn't going to change that one bit.  :P
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline mdijkens

  • Newbie
  • Posts: 34
Re: &H colors dont work as CONST
« Reply #38 on: March 06, 2022, 12:04:50 pm »
I would expect CONST values to match assigned type or condition?
So
Const MYCONST = &HFFFF
a% = MYCONST ' -1
a~% = MYCONST ' 65536
a&= MYCONST '65536

Same with comparing in conditions
~ 2 million lines of BASIC

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: &H colors dont work as CONST
« Reply #39 on: March 06, 2022, 12:27:17 pm »
Ah yes the Chameleon variable type.

Now I wonder if difference between Val and Print along with If.