SCREEN1 = SYSVAR @ JSROM

Anything QL Software or Programming Related.
Andrew
Trump Card
Posts: 214
Joined: Tue Jul 17, 2018 9:10 pm

Re: SCREEN1 = SYSVAR @ JSROM

Postby Andrew » Mon Jun 03, 2019 1:55 pm

tcat wrote:Just an idea, I could actually borrow some fonts from Speccy, or QL just by printing them onto the screen, and then capture that screen memory, to have the raster, possible?

Or you can simply download font files from Dilwyn's site : http://www.dilwyn.me.uk/fonts/index.html


tcat
Super Gold Card
Posts: 553
Joined: Fri Jan 18, 2013 5:27 pm
Location: Prague, Czech Republic

Re: SCREEN1 = SYSVAR @ JSROM

Postby tcat » Mon Jun 10, 2019 1:29 pm

Hi,

I have coded this, ellipse being the longest procedure so far.

Code: Select all

; PLOT    - CALL [start],[x],[y],[col]
; MODE    - CALL [start+2],[mode]
; BLOCK   - CALL [start+4],[x],[y],[col],[w],[h]
; LINE    - CALL [start+8],[x],[y],[col],[x0],[y0]
; CIRC    - CALL [start+12],[x],[y],[col],[r]
; CIRCF   - CALL [start+16],[x],[y],[col],[r]
; ELIP    - CALL [start+20],[x],[y],[col],[a],[b]
; ELIPF   - CALL [start+24],[x],[y],[col],[a],[b]

All procs seem reasonable fast, except BLOCK that I also use for scan line fill, circle and ellipse.
It takes these lines below, is simple but quite slow (as it goes by pixels), actually slower than QDOS. I wish to make it a lot faster?

EDIT same simple slow algo, tidied up, and slightly optimised

Code: Select all

block    link     a4,#-$0c          ;locals bl
bl_x     equ     -$02               ;d1
bl_x1    equ     -$04
bl_y     equ     -$06               ;d2
bl_col   equ     -$08               ;d3
bl_w     equ     -$0a               ;d4
bl_h     equ     -$0c               ;d5
         lea      dctl,a2           ;dctl copy
         move.w   d1,bl_x(a4)       ;x, save locals
         move.w   d1,bl_x1(a4)      ;x1=x copy
         move.w   d2,bl_y(a4)       ;y
         move.w   d3,bl_col(a4)     ;col
         move.w   d4,bl_w(a4)       ;w
         subq.w   #1,bl_w(a4)       ;-1 for DBF
         move.w   d5,bl_h(a4)       ;h
         subq.w   #1,bl_h(a4)       ;-1 for DBF
         move.w   bl_h(a4),d7       ;restore h
height   move.w   bl_w(a4),d6       ;restore w
         move.w   bl_x1(a4),bl_x(a4) ;restore x
width    move.w   bl_x(a4),d1       ;d1=x
         move.w   bl_y(a4),d2       ;d2=y
         move.w   bl_col(a4),d3     ;d3=col
         bsr      plot1             ;pixel x,y,col
         addq.w   #1,bl_x(a4)       ;x=x+1
         dbf.w    d6,width          ;loop w times
         addq.w   #1,bl_y(a4)       ;y=y+1
         dbf.w    d7,height         ;loop h times
         unlk     a4

Many thanks
Tomas
Last edited by tcat on Mon Jun 10, 2019 3:09 pm, edited 3 times in total.


martyn_hill
Super Gold Card
Posts: 516
Joined: Sat Oct 25, 2014 9:53 am

Re: SCREEN1 = SYSVAR @ JSROM

Postby martyn_hill » Mon Jun 10, 2019 2:01 pm

Hi Thomas!

tcat wrote:All procs seem reasonable fast, except BLOCK that I also use for scan line fill, circle and ellipse.
It takes these lines below, is simple but quite slow (as it goes by pixels), actually slower than QDOS. I wish to make it a lot faster?


When I last researched the topic of 'block' fill (e.g. CLS and many other uses), IIRC some additional pre-processing is carried out - certainly in Minerva - so that multi-byte moves can be used to actually paint the required colour-mask - using such tricks as devious combinations of MOVEM.L and/or MOVEP.

Ultimately, we are at the mercy of the DRAM bus-bandwidth - including contention with the 8301 - and reducing the instruction-count needed to paint a given range of video-words, helps to optimise performance...

At one time, I toyed with the idea of generating self-modifying code - I know, the purists will complain :-) - to maximise the use of MOVEM.L's, depending upon the block dimensions and offsets for a given area. It's tedious and I gave up after a while, but it looked promising to eek-out even higher block-painting performance at the expense of complex coding and non-re-entrancy...

Good luck!


User avatar
tofro
QL Wafer Drive
Posts: 1596
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: SCREEN1 = SYSVAR @ JSROM

Postby tofro » Mon Jun 10, 2019 2:56 pm

If you want BLOCK to be faster, you need to handle the vertical borders differently from the inside pixels:

The "inside pixels" that lay on a word boundary can be filled by using simple word moves of the uniform appropriate solid color to the screen memory. Only the left and right remaining border pixels in a scanline need to be set by your "POINT" routine.

Here's a bit of C code (for mode 4) that does exactly that:

Code: Select all

// Dump a rectangular block to the screen
// optimized to only use plot at the left and right edges, and direct
// full unsigned short access where possible
void block4 (int x1, int y1, int w, int h, int col){
   unsigned int xr1;
   unsigned int xr2;
   unsigned int line;
   int i;
   int shortDiff;
   register unsigned short * screenWord;

   // find end of accessable screen memory
   unsigned short * upperLimit = (unsigned short*) (theScreen->lineStartTab [theScreen->yPix - 1] + theScreen-lineLen - 1);
   register int xLim = theScreen->xPix;
   register int yLim = theScreen->yPix;
   int numPixels;
   
   xr1 = (x1 + 7) & 0xfffffff8u; // remove non-short-aligned pixels at the beginning (round up to the next pixel/byte boundary)
   xr2 = (x1 + w) & 0xfffffff8u; // remove non-short-aligned pixels at the end (floor to the next pixel/byte boundary)

   /* This is how many full screen shorts we can fill */
   shortDiff = abs (xr2 - xr1) >> 3;
   
   for (line = 0; line < h; line++) {
     
      // Are we trying to draw outside limits?
      if ((line + y1) >= theScreen->yPix)
         return;

      screenWord = (unsigned short*)(theScreen->lineStartTab [y1 + line] + (xr1 >> 2));
     
      // Draw pixels left of short-aligned border
      numPixels = xr1 - x1;
      for (i = 0; i < numPixels; i++) {
         plot4 (x1 + i, y1 + line, col);
      }

      // Draw short-aligned pixels
      for (i = 0; (i < shortDiff) && (screenWord < upperLimit) /* && (screenWord < theScreen->lineStartTab [y1 + line + 1])*/; i++) {
         *screenWord++ = m4ColorMask [col & 7];
      }

      // draw remaining right pixels
      numPixels = (x1 + w) - xr2;
      for (i = 0; i < numPixels; i++) {
         plot4 (xr2 + i, y1 + line, col);
      }
   }
}


The interesting bit is how to find the number of pixels to the left and right of a scanline of the block that don't make up a uniform word in screen memory - those need to be set by a PLOT routine. The "inner" part of the scanline are all the same and are set by "draw short-aligned pixels" by setting eight pixels per word access. That's obviously way faster than any PLOT routine.

Tobias


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
tcat
Super Gold Card
Posts: 553
Joined: Fri Jan 18, 2013 5:27 pm
Location: Prague, Czech Republic

Re: SCREEN1 = SYSVAR @ JSROM

Postby tcat » Mon Jun 10, 2019 3:06 pm

Hi Tobias,
Thank you for the algo and the idea of faster block fill. Will try to recode into assembly, and share back.
Meanwhile I tidied up simple slow code just for clarity.
Working on the fast variant now.
Tomas


tcat
Super Gold Card
Posts: 553
Joined: Fri Jan 18, 2013 5:27 pm
Location: Prague, Czech Republic

Re: SCREEN1 = SYSVAR @ JSROM

Postby tcat » Wed Jun 12, 2019 1:37 pm

Hi,

Borrowing from the `C' prog, I try to compute, left, right words, instead of plotting leading and trailing dots. Making middle word is easier. I work along this loop. Not perfect so far, not optimal either.

Code: Select all

....
         movea.l  a0,a1             ;screen address x,y

         move.w   bl_lm(a4),d3      ;d3=left mask
         move.w   bl_mm(a4),d4      ;d4=middle mask
         move.w   bl_rm(a4),d5      ;d5=right mask
         move.w   bl_h(a4),d7       ;d7=height
         move.w   bl_wc(a4),d6      ;d6=word count
bl_hl    movea.l  a1,a0             ;restore address
         move.w   d3,(a0)+          ;left word, TODO mask
         move.w   d4,(a0)+          ;middle; TODO loop wc times
         move.w   d5,(a0)           ;right, TODO mask
         lea      128(a1),a1        ;next line
         dbf.w    d7,bl_hl          ;loop h times
bl_exit  unlk     a4

; Common exit
exit     clr.l    d0                ;No error code
         rts

There are cases, no left, nor right words, or only middle one. I seem to take on a difficult path.

Tomas


tcat
Super Gold Card
Posts: 553
Joined: Fri Jan 18, 2013 5:27 pm
Location: Prague, Czech Republic

Re: SCREEN1 = SYSVAR @ JSROM

Postby tcat » Sun Jun 16, 2019 8:09 am

Hi,

I have now a testing BLOCK that goes by words, much faster, compared to a simple version going by pixels.

Is there a way in machine code, to combine MODE 8, say in upper screen, and MODE 4, in lower part?

I wish to mix some graphics in 8 colours, with text on 8x8 raster 4 colours?

Many thanks
Tomas


User avatar
tofro
QL Wafer Drive
Posts: 1596
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: SCREEN1 = SYSVAR @ JSROM

Postby tofro » Sun Jun 16, 2019 9:24 am

That is possible, but tricky (and costing a lot of CPU, i.e. you can only use that technique for programs that spend a lot of time waiting for user input).

The approach goes along the lines of

  • Set up a polling interrupt routine that switches to mode (a), busy waits for around half a screen time, then switches to mode (b).
  • Switching must be done by directly accessing the mode register (MC_STAT, bit 3, $18063) of the hardware. The standard MT.DMODE trap cannot be used (way too slow).
  • As the OS doesn't know that half of the screen is not displayed in the mode it thinks, you need to access the screen directly, rather than using system calls
  • The wait times need to be finely adjusted to exactly hit the end of a scanline when switching. That is almost impossible to achieve along the whole bandwidth of different QLs, with faster and slower memory. You should ensure that your timing loops are completely in contended memory, so you at least can come close.
  • As Gold and SuperGold cards have a completely different timing, you will have to adjust your timing loops accordingly in order to make such a routine run reliably there. I'd start with a plain, unexpanded QL.
The whole procedure is a bit similar to what once was shown as a demo for high-res pictures.


I seem to recall that either Quill or Adventure Writer offered such a split screen technique (That never really worked reliably across all makes of QLs).

Tobias
Last edited by tofro on Sun Jun 16, 2019 10:48 am, edited 1 time in total.


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
Ralf R.
Over Heated PSU
Posts: 131
Joined: Fri Jun 15, 2018 8:58 pm

Re: SCREEN1 = SYSVAR @ JSROM

Postby Ralf R. » Sun Jun 16, 2019 9:37 am

tcat wrote:Is there a way in machine code, to combine MODE 8, say in upper screen, and MODE 4, in lower part?


The Adventure Creation Tool (ACT) from Steve Sutton (marketed by DP) offer this.


Ralf R.
Over Heated PSU
Posts: 131
Joined: Fri Jun 15, 2018 8:58 pm

Re: SCREEN1 = SYSVAR @ JSROM

Postby Ralf R. » Sun Jun 16, 2019 12:10 pm

tofro wrote:I seem to recall that either Quill or Adventure Writer offered such a split screen technique (That never really worked reliably across all makes of QLs).


The Quill Adventure Writing System do not offer any graphics on the QL.



Who is online

Users browsing this forum: No registered users and 7 guests