![]() |
![]() |
#1 |
It's coming back!
Join Date: Jul 2018
Location: comp.sys.amiga
Posts: 762
|
Blitter line mode problems
I'm trying to follow this guide http://www.winnicki.net/amiga/memmap/LineMode.html to blit a line from (9,9) to (309,117), and while it's blitting something, it's not a straight line (see attached image).
The code is as follows. It fills a structure that gets queued up, but on dequeueing the hardware registers get set in exactly the same order, so I'm confident the problem is in this code here: Code:
static void drawLine(ScreenBuffer * screenBuffer, UWORD x1, UWORD y1, UWORD x2, UWORD y2, UWORD colour) { for (int i = 0; i < screenBuffer->depth; i++) { Blit * blit = Blitter_AquireBlit(BLIT_TYPE_LINEDRAW, (Display *) display, screenBuffer); if (!blit) { // KPrintF("Blitter queue full (3).\n"); return; } UWORD dx = ABS((WORD) x1 - (WORD) x2); UWORD dy = ABS((WORD) y1 - (WORD) y2); UWORD octant = 0; if ((dx >= dy && x1 >= x2) || (dx < dy && y1 >= y2)) octant |= AUL; if ((dx >= dy && y1 >= y2) || (dx < dy && x1 >= x2)) octant |= SUL; if (dx >= dy) octant |= SUD; KPrintF("octant = %04lx\n", octant); UWORD dmax = MAX(dx,dy); UWORD dmin = MIN(dx,dy); blit->registers.bltamod = 4 * dmin; KPrintF("bltamod = %04lx\n", blit->registers.bltamod); blit->registers.bltbmod = 4 * (dmax - dmin); KPrintF("bltbmod = %04lx\n", blit->registers.bltbmod); blit->registers.bltapt = (APTR) ((LONG) (4 * dmin - 2 * dmax) & 0x0000ffff); KPrintF("bltapt = %08lx\n", blit->registers.bltapt); blit->registers.bltcon1 = LINEMODE | octant | (blit->registers.bltapt < 0 ? SIGNFLAG : 0); // always set bltcon1 before bltbdat KPrintF("bltcon1 = %04lx\n", blit->registers.bltcon1); blit->registers.bltbdat = 0xffff; blit->registers.bltcmod = screenBuffer->width >> 3; blit->registers.bltdmod = screenBuffer->width >> 3; APTR firstWord = screenBuffer->bitMaps[i] + y1 * (screenBuffer->width >> 3) + (x1 >> 3 & 0xfffe); blit->registers.bltcpt = firstWord; blit->registers.bltdpt = firstWord; UWORD minterm = (colour & 1 << i) ? (ABC | ABNC | NABC | NANBC) : (ANBNC | ABNC); KPrintF("minterm = %04lx\n", minterm); blit->registers.bltcon0 = x1 << 12 | SRCA | SRCC | DEST | minterm; KPrintF("bltcon0 = %04lx\n", blit->registers.bltcon0); blit->registers.bltadat = 0x8000; // set this only after bltcon0 blit->registers.bltafwm = 0xffff; blit->registers.bltalwm = 0xffff; blit->registers.bltsize = dmax * 64 + 66; // blit->registers.bltsize = ((dmax + 1 ) << 6) | 2; KPrintF("bltsize = %04lx\n", blit->registers.bltsize); Blitter_EnqueueBlit(blit); } } Code:
octant = 0010 bltamod = 01B0 bltbmod = 0300 bltapt = 0000FF58 bltcon1 = 0011 minterm = 00CA bltcon0 = 9BCA bltsize = 4B42 octant = 0010 bltamod = 01B0 bltbmod = 0300 bltapt = 0000FF58 bltcon1 = 0011 minterm = 0050 bltcon0 = 9B50 bltsize = 4B42 ... Ignore the green bit at the bottom, that's unrelated. Last edited by deimos; 21 November 2021 at 11:32. |
![]() |
![]() |
#2 |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 54
Posts: 4,534
|
My values for (9,9)-(309,117):
(as usual mine is an asm optimized routine) Code:
BLTCON0 0x9b4a BLTCON1 0x0051 BLTAFWM 0xffff BLTALWM 0xffff BLTCPTx BPLxPTx+0x0169* BLTAPTL 0xffac BLTDPTx BPLxPTx+0x0169* BLTSIZE 0x4b42 BLTCMOD 0x0028 BLTBMOD 0x00d8 BLTAMOD 0xfe80 BLTDMOD 0x0028 Some of your values seem out. |
![]() |
![]() |
#3 |
It's coming back!
Join Date: Jul 2018
Location: comp.sys.amiga
Posts: 762
|
|
![]() |
![]() |
#4 | |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 54
Posts: 4,534
|
Quote:
Call me if you need other reference values. |
|
![]() |
![]() |
#5 | |
It's coming back!
Join Date: Jul 2018
Location: comp.sys.amiga
Posts: 762
|
Quote:
I now have a straight line. I don't know where the problems were with the original, but now I don't really care. [EDIT: There's at least one typo of mine.] I'm printing out the same debug info, and I have different numbers to you in bltaptl, bltbmod and bltamod. Your values are all exactly half of mine. Code:
BLTCON0 0x9b4a == 0x9B4A BLTCON1 0x0051 == 0x0051 BLTAFWM 0xffff == 0xFFFF BLTALWM 0xffff == 0xFFFF BLTCPTx BPLxPTx+0x0169* == 0x0001C9C0 BLTAPTL 0xffac == 0xFF58 BLTDPTx BPLxPTx+0x0169* == 0x0001C9C0 BLTSIZE 0x4b42 == 0x4B42 BLTCMOD 0x0028 == 0x0028 BLTBMOD 0x00d8 == 0x01B0 BLTAMOD 0xfe80 == 0xFD00 BLTDMOD 0x0028 == 0x0028 Last edited by deimos; 09 October 2019 at 12:36. |
|
![]() |
![]() |
#6 | ||
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 54
Posts: 4,534
|
Quote:
bltamod (4Y-4X) and bltbmod (4Y) define the slope (Y/X). bltaptl is an accumulator and must be preloaded with the initial (2Y-X). If the values are consistent, the line is good. Quote:
If you write in the same position, line is canceled. Instead, for a line that is always drawn, use 0xca. |
||
![]() |
![]() |
#7 |
It's coming back!
Join Date: Jul 2018
Location: comp.sys.amiga
Posts: 762
|
This is what I'm stuck on at the moment, what should I use for the bitplanes the need the line bits cleared, so that I can do different coloured lines?
EDIT: I think it's 0x3a, as in: Code:
UWORD minterm = (colour & 1 << i) ? NANBC | NABC | ABNC | ABC : NANBC | NABC | ANBNC | ANBC; Last edited by deimos; 08 October 2019 at 17:15. |
![]() |
![]() |
#8 |
ex. demoscener "Bigmama"
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,664
|
to clear the bitplane, you need to 'and' it with the inverse of the source.
|
![]() |
![]() |
#9 |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 54
Posts: 4,534
|
Yes, but some explanation is due (and a little trick).
0xca minterm is this operation: D = AB + A'C There is two constant here: BLTBDAT as a mask for the line and BLTADAT as the 'pixel'. Usually BLTBDAT=0xffff because you want a full line and BLTADAT(MSB)=1 because one pixel large line. The blitter operation mean: - for the AB part: write 1 to destination when (A and B) == 1, so everytime Bresenham's algorithms inside blitter decide is the right time to make an output. [EDIT: If you setup a different B mask you expect a dotted line, if you setup a different A 'pixel' you output more than one at the same time (interesting effects ![]() This is right but for a different minterm, see successive messages. Probably the minterm is often (mis-)used because is the classical bob cookie-cut (with mask in A). But in this case suppose you have A=1,B=0,C=1, you expect D=1, but no.. so works only for mask=0xffff ] - for the A'C part: when A=0 (no 'pixel' output) write 1 to destination if required (that is with C=1). Result: you write a line over the background. What you have done setting a minterm of 0x3a is reversing the mask effect or rather making A the only relevant part. The operation is now D = AB' + A'C If you have a B mask of 0xffff then the first operand is alway 0. So for A'C you usually have C at output excluding when 'pixel', where you output 0 with A=1. Indirectly exactly what you want ![]() Of course a negated 0xffff B mask is no more a mask (it's always 0) so also D = A'C works (minterm 0x0a). And this give you the possibility to not even setup BLTBDAT because its ignored ![]() If you want you can also use other valid combinations, I happened to use rather strange minterms in the past ![]() Last edited by ross; 08 October 2019 at 23:07. Reason: [] |
![]() |
![]() |
#10 | |
It's coming back!
Join Date: Jul 2018
Location: comp.sys.amiga
Posts: 762
|
Quote:
Is there any advantage to not having to set up BLTBDAT apart from the initial cost of putting ones in it? And is there the equivalent for the set operation / 0xCA minterm? |
|
![]() |
![]() |
#11 | |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 54
Posts: 4,534
|
Quote:
-- I am still gathering ideas because all my blabbling on BLTBDAT made me think that many linedrawing routines work only because it's preset to 0xffff. But they should use a different (and more correct) minterm in case of mask usage. Please wait next message. |
|
![]() |
![]() |
#12 |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 54
Posts: 4,534
|
Right minterm for a XOR masked linedraw:
0x6a -> D = A'C + B'C + ABC' Right minterm for a OR masked linedraw: 0xea -> D = C + AB Right minterm for a CLEAN masked linedraw: 0x2a -> D = A'C + B'C Obviously it does not hurt to use these minterm also in the 0xffff mask case. I leave them as a reference also for me and I'll correct it if necessary, actually I didn't think too much about it ![]() Last edited by ross; 08 October 2019 at 21:55. Reason: damn, I've edited something that was right from the start :) |
![]() |
![]() |
#13 |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 54
Posts: 4,534
|
|
![]() |
![]() |
#14 |
It's coming back!
Join Date: Jul 2018
Location: comp.sys.amiga
Posts: 762
|
Thanks,
My initial tests with Code:
UWORD minterm = (colour & 1 << i) ? 0xfa : 0x2a; I'll also slap some different background colours in as a complete test, just because it's easy. One last line draw related question... back in '89 or so I was trying to blit lines onto interleaved bitmaps but struggled with the occasional line being wrong, there would be odd pixels of the wrong colour as if Bresenham had decided to go up or down one pixel earlier or later for some bitplanes. I'm going to try and change my code to use interleaved bitmaps because it makes sense for other things, but can you think of any reason why line blitting won't work on what are essentially very wide bitplanes, which just the modulos changes to reflect this? |
![]() |
![]() |
#15 | |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 54
Posts: 4,534
|
This:
Code:
UWORD minterm = (colour & 1 << i) ? 0xfa : 0x2a; Code:
UWORD minterm = (colour & 1 << i) ? 0xfa : 0x0a; Quote:
|
|
![]() |
![]() |
#16 | |
It's coming back!
Join Date: Jul 2018
Location: comp.sys.amiga
Posts: 762
|
Quote:
EDIT: I think you meant 0x0a? EDIT 2: Never mind, I think I misunderstood what you meant by "CLEAN masked linedraw". |
|
![]() |
![]() |
#17 | |||
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 54
Posts: 4,534
|
Quote:
Quote:
Quote:
![]() But I will do more tests because there is a lot of contrast online (even HRM use 0xca or 0x4a minterms and some wiki report strangeness for line draw mode..) I've also some questions for Toni ![]() I've never had any problems with my routine, but understanding all the cases would be better. |
|||
![]() |
![]() |
#18 |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 54
Posts: 4,534
|
Ok, questions for Toni or who can answer me.
All are related to Blitter in LINE mode. BLTAPT act as an accumulator with initial value (4 * dy) - (2 * dx). On HRM (and other sources) BLTAPT[H&L] is accessed as an .l register (like as if it were actually a pointer). But if you setup only BLTAPTL as a signed 16bit value seems that is working anyway. What's the right way? Upper bits of BLTCON1 are called TEXTURE(0-3). Why? From what I understand they do the same thing as the normal mode ie a shift of the content of B (BSH(0-3)). The last question concerns the use of mask B and the 'famous' minterms 0xca and 0x4a which are used as an example for OR and XOR operations. (and you can find them in various available blitter examples/sources) Why talk about masks (how to setup and use) if they don't work the way they should with values <>0xffff? (well this need some better tests that I've not had time to do ![]() Last edited by ross; 09 October 2019 at 12:22. Reason: [] |
![]() |
![]() |
#19 | |||
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,611
|
Quote:
Quote:
BDAT gets loaded to internal shift register, pre-shifted by TEXTURE value. Same as block mode. The rest is different: bit 0 of shifter selects if internal BDAT (BHOLD) is FFFF (1) or 0000 (0). After each processed line pixel, shift register is shifted (rotated) by one bit. (Or shifter is re-loaded after 16 bits, same result anyway) Line gets "textured" with 16-bit repeating pattern. Quote:
|
|||
![]() |
![]() |
#20 | |||
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 54
Posts: 4,534
|
Quote:
![]() Quote:
![]() BHOLD is used because with Bresenham algorithms you could emit single pixel at a time (so you can also have different r/w operations per single word cell). For this reason you need to 'propagate' the instantaneus BDAT bit 0 for when you apply the minterm operation (to make sure the right B bit is current despite the TEXTURE rotation). As you said this allows in practice a textured mask along the slope and no longer per word as on bitblock. In fact I had seen by eye that it worked this way but always interesting to understand how and why. Quote:
![]() Thanks Toni! Last edited by ross; 09 October 2019 at 17:28. Reason: punctuation |
|||
![]() |
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
![]() |
||||
Thread | Thread Starter | Forum | Replies | Last Post |
Blitter line-drawing mode? | E-Penguin | Coders. Blitz Basic | 2 | 13 April 2019 21:37 |
Blitter: clean-up line drawing and fill mode idle cycles. | ross | Coders. Asm / Hardware | 9 | 12 May 2018 22:32 |
Blitter line mode examples? | LuigiThirty | Coders. Asm / Hardware | 4 | 17 August 2017 08:26 |
Keep Active control panel "Line Mode" and "Interlaced Line Mode" | Zilog | request.UAE Wishlist | 4 | 02 August 2014 23:08 |
Line mode blitter | absence | Coders. General | 4 | 25 September 2009 20:50 |
|
|