QL Graphics

Anything QL Software or Programming Related.
User avatar
dilwyn
Mr QL
Posts: 2753
Joined: Wed Dec 01, 2010 10:39 pm

Re: QL Graphics

Post by dilwyn »

Back in the late 1980s I wrote this little routine in assembler which has been used in some of my programs such as Image Processor. Not infallible by any means (and doesn't use tofro's even number of flash bits suggestion). You are welcome to use or adapt this code without acknowledgement at all.

LET mode_number = GUESS(base_address,number_of_bytes)
returns 0 for mode 4, 8 for mode 8

Just takes the brute force approach of assuming that mode 8 screens contain no flashing - any flash bits set would be green bits from a mode 4 picture. Could be adapted within the DBF loop to count flash bits set to a given threshold number by statistically looking at a collectionof mode 8 screens from old games for typically how many flash bits set in mode 8 screens on average. Works adequately well for screens without any flashing as it stands. The two parameters are simply to allow for a screen anywhere in memory (not just at the video address) can be used.

In my programs I took the approach of a user confirmation - the programs said something like "I think this is mode 4, do you agree Yes/No?". Obviously you can't do this when building a list of thumbnails. What do you hope to do, an approach like Windows perhaps where the folders contain a list of thumbnails and if any images are found to change (maybe the .db or database file might contain a list of image files and their update dates and if any dates changed) update the list?

Code: Select all

* routine for Screen Compression to GUESS if a screen is mode 4 or 8
* by checking the flash bits set - in mode 8 no or very few will be set
* while in mode 4 the greens set will correspond to mode 8 flash bits
* so can be used as a reasonable guide to guessing the mode number.
* Not infallible! Mode 8 screens WITH flashing will confuse it, as will
* mode 4 screens with no green of course.
        move.w  $110,a0         ;bp.init
        lea     procblock,a1    ;procedures table
        jsr     (a0)            ;link to basic
        rts                     ;back to BASIC

procblock       dc.w    0,0,1,entry-*
        dc.b    5,'GUESS'
        dc.w    0
        
err_rpt moveq   #-15,d0         ;err.bp
        rts                     ;back to BASIC
entry   move.w  $118,a0         ;ca.gtlin get long word parameters
        jsr     (a0)
        bne.s   err_rpt         ;oops
        subq.w  #2,d3           ;exactly 2 parameters?
        bne.s   err_rpt         ;oops
        move.l  0(a6,a1.l),a0   ;base address
        move.l  4(a6,a1.l),d0   ;bytes to check
        lsr.w   #1,d0           ;DIV 2 to convert to WORDS
        subq.w  #1,d0           ;prepare to DBF

loop    move.w  (a0)+,d1        ;word from screen
        andi.w  #$5500,d1       ;check flash bits
        tst.w   d1              ;non zero (flashing?)
        bne.s   mode4           ;flash bits set must be mode 4
        dbf     d0,loop         ;any more to do?
* no flash bits set, must be mode 8
mode8   moveq   #8,d0           ;prepare to return MODE 8
        bra.s   return          ;jump to stacking part
mode4   moveq   #0,d0           ;MODE 4
return  moveq   #3,d4           ;return word length integer
        adda.l  #6,a1           ;adjust RI stack pointer
        move.l  a1,$58(a6)      ;into bv.rip
        move.w  d0,0(a6,a1.l)   ;put mode number on stack
        moveq   #0,d0           ;no error
        rts                     ;back to BASIC      


User avatar
tofro
Font of All Knowledge
Posts: 2685
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: QL Graphics

Post by tofro »

Pr0f wrote:Flash must be in pairs - is that always true ?

What if an entire line was to be set for flash, and somebody made use of the fact that flash would be reset at the end of the scanline - then you'd only have one flash bit set at the start of a line and no corresponding toggle off. In my opinion that could be classed as 'lazy programming' but hey, it's supported ;-)

Sorry to be a devils spanner polisher...
No, it's not - that was what I was trying to say. A set FLASH bit is valid until it's unset or until the end of the scanline. That is why I was saying it's a high probability they occur in pairs - all system functions seem to be switching off FLASH before the end of the scanline (Which doesn't mean you cannot produce such screens, but not using S*BASIC or documented system functions) . And a picture that has most of its right-hand side flashing is probably not worth watching anyways...

There's definitely no 100% save way to distinguish MODE 4 and MODE 8 pictures by just looking at the bitmap. But there are reasonably safe guesses.

Tobias


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
User avatar
Pr0f
QL Wafer Drive
Posts: 1298
Joined: Thu Oct 12, 2017 9:54 am

Re: QL Graphics

Post by Pr0f »

tofro wrote:.... And a picture that has most of its right-hand side flashing is probably not worth watching anyways...

Yes - agreed :-) - was trying to get my head around how harsh that might look as well. Definitely an edge case...


martyn_hill
Aurora
Posts: 909
Joined: Sat Oct 25, 2014 9:53 am

Re: QL Graphics

Post by martyn_hill »

"Devil's spanner polisher" - I love it!

Never come across that term before (but fully understand its intent.)

And yes, if an extreme end of a scan-line is contiguous FLASH, it must (?) follow that either the first FLASH toggle bit or the last toggle bit would necessarily be dropped.

I wonder if anyone (Nasta?) knows whether the 8301 starts flashing in the _next_ pixel having detected a FLASH bit set, or on the current pixel? And whether the same applies at the end of the FLASH. (We know it is auto disabled anyway after the end of a scanline.)

I'm guessing that you'll only be guaranteed of pairs if the FLASH ends before the RHS (otherwise, you could never see the last pixel FLASHing.)

Anyways, the assumption that the vast majority of saved images will not have any FLASH at all still seems a reasonable (but less than 100%) starting-point. If we are scanning many images (which seems to be Per's use-case), we're probably talking about repositories generated by an emulator - and as far as I am aware, none of the popular emulators even bother supporting HW FLASH.

It then just remains to find the optimum (in terms of both speed vs coverage/accuracy) set of test-points across the display.

An interesting diemna!


User avatar
janbredenbeek
Super Gold Card
Posts: 629
Joined: Wed Jan 21, 2015 4:54 pm
Location: Hilversum, The Netherlands

Re: QL Graphics

Post by janbredenbeek »

martyn_hill wrote: I wonder if anyone (Nasta?) knows whether the 8301 starts flashing in the _next_ pixel having detected a FLASH bit set, or on the current pixel? And whether the same applies at the end of the FLASH. (We know it is auto disabled anyway after the end of a scanline.)
I've done some research with this (having written a Viewdata/Prestel terminal emulator). When you set FLASH on, the characters are actually written to the display memory with the leftmost and rightmost flash bit set. Since all character patterns have their leftmost bit reset (i.e. the resulting pixel is background colour), the remaining pixels will start flashing between foreground colour (if the corresponding bit is set) and background colour (which is the colour of the leftmost pixel which has flash bit set). This will last up to and including the rightmost pixel (which has again flash bit set). So when PRINTing with FLASH on, actually every character will turn flash on and off again.

So to answer your question: flashing starts at the next pixel (which will flash between its own colour and the colour defined by the pixel which turns flash on) and lasts until (and including) the next pixel which turns flash off, or the end of the scan line.

regards, Jan.


User avatar
pjw
QL Wafer Drive
Posts: 1286
Joined: Fri Jul 11, 2014 8:44 am
Location: Norway
Contact:

Re: QL Graphics

Post by pjw »

Thanks for all the tips and support (so far ;)!) To be quite honest, this particular problem bores
me to tears - Perhaps thats why I find it hard (or vice versa..) Low-level stuff is so messy, I
find ;) All I want to do is create the basis for a thumbnail viewer for as many graphic file
formats as possible, and then these irritating, possibly unsolvable, problems appear and rain
on my picnic.

Anyway, this wee issue is only one of a few: There are other headless screen dumps around,
with no way of telling what they are! The first steps will be to analyse the directory and file
names for any clues, the second is to scan the files for clues, where appropriate. The third
attack relates to file sizes. My current solution can be seen below. Any suggestions for
improvements or different approaches are welcome! (Which is my only reason for plonking
it here in your face!)

The fourth strategy is to allow considerable freedom to configure the program to meet local
requirements. And finally, the ultimate cop-out: User input! I intend to allow a user to
correct images that dont look right by clicking on them and choosing the option to enter the
correct information, or try and err until satisfied. Once it looks right, it will be kept in the
"database" until the original file is updated or deleted.

Code: Select all

1 RESTORE
2 DIM xdim%(14), ydim%(15)
3 FOR i% = 0 TO DIMN(xdim%): READ xdim%(i%)
4 FOR i% = 0 TO DIMN(ydim%): READ ydim%(i%)
5 DATA 256, 512, 640, 720, 768, 800, 1024, 1280, 1360, 1366, 1400, 1440, 1600, 1680, 1920
6 DATA 256, 280, 350, 384, 480, 512, 576, 600, 720, 768, 800, 900, 960, 1024, 1050, 1080
7 :
8 REMark Results arrays
9 DIM rx%(6), ry%(6), rm%(6)
10 :
11 :
100 REMark     Test harness
102 ch = FOPEN('con'): CLS#ch
104 REMark Actual file sizes for testing purposes (not part of the routine)
106 DIM tst(16)
108 FOR i% = 0 TO DIMN(tst): READ tst(i%)
110 DATA 1.96608E6,393216,691200,829440,960000,1.572864E6,1.8432E6,1.049088E6,256000,86400
112 DATA 345600,414720,480000,786432,921600,983040,1.024E6,1.2288E6,1.31072E6
114 DATA 1.04448E6,1.049088E6,1.47E6,1.296E6,1.44E6,1.6384E6,1.764E6,2.0736E6
116 :
118 FOR n = 0 TO DIMN(tst)
120  r = GetScrDmpDim(tst(n), rx%, ry%, rm%)
122  PRINT#ch; CDEC$(tst(n), 10, 0),
124  IF r >= 0 THEN
126   PRINT#ch; 'found'! r + 1! 'possible'
128   FOR i% = 0 TO r
130    PRINT#ch; rx%(i%)! 'X'! ry%(i%), : REMark 'mode'! rm%(i%)
132    SELect ON rm%(i%): = 0: m$ = 'QL': = 1: m$ = '16': = REMAINDER : m$ = '32/33'
134    PRINT#ch; 'mode'! m$
136   END FOR i%
138   PAUSE#ch
140  ELSE
142   PRINT#ch; 'Not known'
144  END IF
146  PRINT#ch
148 END FOR n
150 IF JOBID: PAUSE#ch: QUIT
152 :
154 :
500 DEFine FuNction GetScrDmpDim(fl, r.x%, r.y%, r.m%)
502 LOCal i%, ty%, t, f, c%
504 REMark GLOBal xdim%, ydim%
506 :
508 IF INT(fl / 8) <> fl / 8: RETurn -15
510 IF fl = 32768 THEN
512  r.x%(0) = 512: r.y%(0) = 256: r.m%(0) = 0: RETurn 0
514 END IF
516 :
518 c% = -1
520 REMark Try 8bit
522 FOR i% = 0 TO DIMN(xdim%)
524  t = fl / xdim%(i%)
526  ty% = GetYsize%(t)
528  IF ty% THEN
530   c% = c% + 1
532   r.x%(c%) = xdim%(i%): r.y%(c%) = ty%: r.m%(c%) = 1
534  END IF
536 END FOR i%
538 :
540 REMark Try 16bit
542 f = fl / 2
544 FOR i% = 0 TO DIMN(xdim%)
546  t = f / xdim%(i%)
548  ty% = GetYsize%(t)
550  IF ty% THEN
552   c% = c% + 1
554   r.x%(c%) = xdim%(i%): r.y%(c%) = ty%: r.m%(c%) = 2
556  END IF
558 END FOR i%
560  :
562 REMark Try QL modes
564 f = f * 8
566 FOR i% = 0 TO DIMN(xdim%)
568  t = f / xdim%(i%)
570  ty% = GetYsize%(t)
572  IF ty% THEN
574   c% = c% + 1
576   r.x%(c%) = xdim%(i%): r.y%(c%) = ty%: r.m%(c%) = 0
578  END IF
580 END FOR i%
582 RETurn c%
584 END DEFine GetScrDmpDim
586 :
588 DEFine FuNction GetYsize%(tz)
590 LOCal j%, s%
592 REMark Uses caller's LOCals
594 REMark GLOBal xdim%, ydim%
596 :
598 IF i% < 3: s% = 0: ELSE : s% = i% - 2
600 FOR j% = s% TO DIMN(ydim%)
602  IF ydim%(j%) >= xdim%(i%): RETurn 0
604  IF tz = ydim%(j%): RETurn ydim%(j%)
606 END FOR j%
608 RETurn 0
610 END DEFine GetYsize%
612 :
614 :
Of course this method falls flat if a user takes advantage of SMSQmulator's infinitely variable
screen sizes - and then goes and dumps them! My response is to put the possible dimensions
into the config file, then each user can devise their own version of Hell..


Per
dont be happy. worry
- ?
User avatar
tofro
Font of All Knowledge
Posts: 2685
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: QL Graphics

Post by tofro »

martyn_hill wrote: I wonder if anyone (Nasta?) knows whether the 8301 starts flashing in the _next_ pixel having detected a FLASH bit set, or on the current pixel?
That's in the Technical Guide, no need to bother Nasta ;)
Technical Guide wrote: The flash bit operates as a toggle:

when set for the first time, it freezes the background colour at the value set by R, G and B, and starts flashing at the next bit in the line; when set for the second time, it stops flashing. Flashing is always cleared at the beginning of a raster line.
That is, the current pixel sets the background color of the flashing area, which starts at the next pixel after the one that has the flash bit set. So the flashing seems to be happening between the pixels that have the FLASH bit set.

Tobias


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
martyn_hill
Aurora
Posts: 909
Joined: Sat Oct 25, 2014 9:53 am

Re: QL Graphics

Post by martyn_hill »

Aha! You have it - thanks.

So, this description would imply that the very first pixel on a scanline cannot be made to FLASH (as flashing actually begins at the next pixel.)

I'll test that on my QL this weekend - had never noticed a 'missing' flashing pixel on the LHS - but then I practically never use flash :-)


martyn_hill
Aurora
Posts: 909
Joined: Sat Oct 25, 2014 9:53 am

Re: QL Graphics

Post by martyn_hill »

Whilst Per has moved on to to fry bigger fish :-)

I thought I'd close the Mode4/Mode8 'sample-point' conversation...

Should anyone find it of any value, the address offsets (integer) for a set of 127x test-points forming a spiral, based on the 32k QL display can be found attached as a .txt file and saved as spiral_offsets.zip

The pattern itself looks like:
spiral_testpoints.png
:-)
Attachments
spiral_offsets.zip
TXT file of integer offsets within a 32k QL screen forming a spiral
(517 Bytes) Downloaded 125 times


User avatar
pjw
QL Wafer Drive
Posts: 1286
Joined: Fri Jul 11, 2014 8:44 am
Location: Norway
Contact:

Re: QL Graphics

Post by pjw »

Thanks a lot for this, Dilwyn. Yes, I may take you up on your offer! Have to check it out first, but I trust it will let me off the hook :) Any possible improvements can come later.
What do you hope to do, an approach like Windows perhaps where the folders contain a list of thumbnails and if any images are found to change (maybe the .db or database file might contain a list of image files and their update dates and if any dates changed) update the list?
Something like that. I started by keeping each thumbnail image (thmbs for short) in the same directory, with the same name but different extension called _tb. Thats quick and easy, but as you soon become aware, there are problems with that approach. So now Im trying a zipped database, one for each folder, tucked away out of sight. That has other issues - such as maintenence. Its slow work, and I have other projects on the go, so dont hold your breath ;)


Per
dont be happy. worry
- ?
Post Reply