BSJR wrote: Sun Nov 06, 2022 1:45 pm
<>This is not entirely true.
When in mode 32: COLOUR_NATIVE: PAPER $1F: CLS: gives bleu, :PAPER $F800: then gives red as in rrrrrggg.gggbbbbb.
Only in PIC and SPR files are the bytes reversed as in a 16-bit BMP.
I think its the other way, Bob. Did you actually try PIXEL32%? Add the following few lines to have a go:
BSJR wrote: Sun Nov 06, 2022 1:45 pm
<>This is not entirely true.
When in mode 32: COLOUR_NATIVE: PAPER $1F: CLS: gives bleu, :PAPER $F800: then gives red as in rrrrrggg.gggbbbbb.
Only in PIC and SPR files are the bytes reversed as in a 16-bit BMP.
I think its the other way, Bob. Did you actually try PIXEL32%? Add the following few lines to have a go:
I have not tried Dilwyn's S*Basic function but your own RPIX% which confirms what QCP also told me.
: COLOUR_QL: PAPER #1,4: CLS
: PRINT HEX$(RPIX%(#1,2,2),16)
This gets me a green window on my m32 QPC2 and returns $07C0, as in 'rrrrrGGG.GGGbbbbb'.
'GGGbbbbb.rrrrrGGG' would have returned $C007, a dark red.
Basically, what we need is to sort out whether the byte-reversed Pixel32% is correct, or that the original one (similar to the Mode 33 version) is correct.
I haven't got a mode 33 display system to compare the results, I'm afraid (although I could probably try to persuade QemuLator to use its Q60 display, I don't know how it handles the endian on Intel systems for display purposes). Equally, I don't know if SMSQ/E on mode 32 systems detects the byte order and transparently reverses them so that byte reversal is unnecessary (ironically this would make both Per and Bob's answers correct in a way!).
It's be interesting, for example, to compare a PEEK_W of a colour word with two PEEKs of the consecutive addresses to see what's going on, might do that when I'm back later.
This gets more and more interesting the more we look at it (enters geek mode)
Once we get a definitive answer, I'll ensure that the Pixelxx% are amended accordingly and make them available from my website for all to use.
I dont know if I have the proper vocabulary for this, but heres how I
understand it:
In mode 32 the formal colour designation is of the form
1. rrrrrggggggbbbbb
in other words, 5 bits red, 6 bits green and 5 bits blue. See Tony Tebby's
GD2-V2.doc rev. 28.05.2001. So this is how you present the colours to the
driver in NATIVE mode.
would produce red, green and blue stripes, as expected.
However, presumably for technical reasons, as Intel-like machines operate
internally with Little-endian numbers, the system switches the bytes
around. For the same reason the sprite and PICture format maintain the
colour information in this internal format, ie:
2. gggbbbbbrrrrrggg
See the SMSQ/E documentation dev8_extras_doc_display_txt.
So values fetched from within the system, eg off the screen as PIXEL32%
and RPIX% do or from the driver as my GETCOL% does, get the Little-endian
(2) version of the colour code, and so to be able to give that back to the
system in the form of INK, PAPER, BLOCK, etc colours they must be switched
to Big-endian (1). However, to use those colour codes to produce sprites or
PICtures, they have to be switched back again! - Or simply left in their
internal, Little-endian state, as you do when you create a screen dump
or a PICture.
It MIGHT have been simpler (at least for us punters) to have just
designated (2) as the formal colour code format, but we are where we are.
I presume the implementers had their reasons.
Mode 33 has quirks too - nothing quite like this, though, but thats another
story.
Per
I love long walks, especially when they are taken by people who annoy me.
- Fred Allen
So in relaity it doesn't matter too much as long as you manage to remember and work out where the red, green and blue bits of the colours are! I remember this causing me brain aches when it came to working out the mode conversions in programs like BMP! Luckily, Bob sorted out any bugs in that one.
Going through this step by step to see the results in practice for mode 32:
RED. Write a red pixel (INK 2) to the screen. The colour word reads as follows:
PEEK_W the address of this pixel gives 248, binary 0000 0000 1111 1000. PEEK the lower address gives 0 (half the nil green plus the nil blue component GGGBBBBB) and PEEK the higher address gives 0, the red component and the other half of the green RRRRRGGG.
GREEN. Write a green pixel (INK 4) to the screen. The colour word reads back as follows:
PEEK_W the address of this pixel gives -16377, binary 1100 0000 0000 0111. PEEK the lower address gives 192 (half the green and the nil blue component GGGBBBBB) and PEEK the higher address gives 7, the nil red component and the other half of the green RRRRRGGG.
BLUE. Write a blue pixel (INK 1) to the screen. The colour word reads back as follows:
PEEK_W the address of this pixel gives 7936, binary 0001 1111 0000 0000. PEEK the lower address gives 31 (nil green and the 5 blue bits) and PEEK the higher address gives 0, nil red and nil green in the RRRRRGGG bits.
So as long as you know where the red, green and blue bits are, you can work out where and how do your own calculations when you want to manipulate the colours.
If you PEEK_W a mode 32 display you get GGGBBBBB RRRRRGGG which is byte reversed according to the docs. Byte reversing this gives you RRRRRGGGGGGBBBBB as Per says, and this makes it a bit easier to handle since the 6 green bits are now together and easier to handle and do calculations with.
So both approaches can be correct, it becomes a question of whether we want to end up with bits in order, or in the form they are stored. Maybe the answer as far as my functions are concerned is to simply PEEK_W the value in mode 32 (like PIXEL33%) but provide a byte-reversal routine for where the order of the two bytes is important. I think I'll do that and document with the functions why the byte reversal may or may not be important, depending on what you want to do.
So, through an international collaboration between Norway, The Netherlands and Wales, we seem to have got to here, where I have the "compromise" solution to reading colours from the screen.
For Mode 32 (QPC2, QXL, etc) we have two functions. PIXEL32% just reads the colour word for a pixel from the screen memory, while PIXEL32_REV% returns the colour word value byte reversed as Per has explained.
If we're OK with this now, I'll write a very short text to go with this and put it on my website.
1000 DEFine PROCedure ScreenDetails
1010 REMark QDOS ROM defaults
1020 screenbase = 131072 : REMark base address of screen
1030 screenllen = 128 : REMark screen line width in bytes
1040 IF VER$ = 'HBA' THEN
1050 REMark use SBASIC functions on hires systems
1060 screenbase = SCR_BASE
1070 screenllen = SCR_LLEN
1080 END IF
1090 END DEFine ScreenDetails
1100 :
1110 DEFine FuNction PIXEL4%(x,y)
1120 LOCal screenbase,screenllen,pixel,word,green,red,addr
1130 ScreenDetails
1140 pixel = 7-(x MOD 8) : REMark pixel number across colour byte
1150 word = 2*(x DIV 8)
1160 addr = screenbase+(y*screenllen)+word
1170 green = 4*((PEEK(addr)&&(2^pixel))<>0)
1180 red = 2*((PEEK(addr+1)&&(2^pixel))<>0)
1190 RETurn green+red+(green<>0 AND red<>0) : REMark 4+2->7 for white
1200 END DEFine PIXEL4%
1210 :
1220 DEFine FuNction PIXEL8%(x,y)
1230 LOCal screenbase,screenllen,pixel,word,green,red,blue,addr
1240 ScreenDetails
1250 pixel = 7-((x&&254) MOD 8) : REMark pixel number across colour byte
1260 word = 2*(x DIV 8)
1270 addr = screenbase+(y*screenllen)+word
1280 green = 4*((PEEK(addr)&&(2^pixel))<>0)
1290 red = 2*((PEEK(addr+1)&&(2^pixel))<>0)
1300 blue = (PEEK(addr+1)&&(2^(pixel-1)))<>0
1310 RETurn green+red+blue
1320 END DEFine PIXEL8%
1330 :
1340 DEFine FuNction PIXEL16%(x,y)
1350 REMark returns value of MODE 16 (256 colour) pixel from screen
1360 ScreenDetails
1370 RETurn PEEK(screenbase+(y*screenllen)+x)
1380 END DEFine PIXEL16%
1390 :
1400 DEFine FuNction PIXEL32%(x,y)
1410 ScreenDetails
1420 REMark returns MODE 32 colour as GGGBBBBB RRRRRGGG as stored in memory
1430 RETurn PEEK_W(screenbase+(y*screenllen)+(2*x))
1440 END DEFine PIXEL32%
1450 :
1460 DEFine FuNction PIXEL32_REV%(x,y)
1470 LOCal addr,word
1480 ScreenDetails
1490 addr = screenbase+(y*screenllen)+(2*x)
1500 REMark byte reverse MODE 32 systems
1510 REMark to get RRRRRGGG GGGBBBBB
1520 word = PEEK(addr+1)*256 + PEEK(addr)
1530 IF word > 32767 THEN word = word-65536
1540 RETurn word
1550 END DEFine PIXEL32_REV%
1560 :
1570 DEFine FuNction PIXEL33%(x,y)
1580 REMark return value of mode 33 pixel
1590 ScreenDetails
1600 REMark colour is GGGGGRRR RRBBBBBW
1610 RETurn PEEK_W(screenbase+(y*screenllen)+(2*x))
1620 END DEFine PIXEL33%
Not sure I agree with the premise, Dilwyn. The reversed values are the Little-endian, internal ones. The "design format" is rrrrrggggggbbbbb! It is this format to use for setting colour values in INK, PAPER, BLOCK and the like, so that is the value Id expect to get when I use PIXEL32%.. I think doing it the other way will just propagate the confusion.
The Endian issue is one of the reasons I love 68 and hate 86! Little-endian is designed by engineers for machines, not for people. People like 1234 (one thousand two hundred and thirty four). Why should we write it, or even have to think of it as 3412?
Anyway, do as you please.
BTW the 3 last functions in the code above are all missing the x, y parameters.
Per
I love long walks, especially when they are taken by people who annoy me.
- Fred Allen