Jump to content

Photo

hacking on a scanline fill for libti99


6 replies to this topic

#1 tschak909 OFFLINE  

tschak909

    River Patroller

  • 3,225 posts
  • Location:USA

Posted Fri Feb 15, 2019 5:41 PM

Hey guys,

as part of trying to get some nice to haves in PLATOTERM, I've taken a whack at getting a flood fill implemented for paint functions.

 

I'm using the same scan-line fill algorithm that I've used in other ports, but for some reason, things are going kind of nutty, and I'd like to figure out why..?

#include <conio.h>
#include <vdp.h>

#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
#define true 1
#define false 0

unsigned char bm_getpixel(int x, int y)
{
  unsigned int addr = ((x>>3)<<3) + ((y>>3)<<8) + (y&0x07) + gPattern;
  VDP_SET_ADDRESS(addr);
  return CHECK_BIT(VDPRD,(x%8));
}

void paint(int x, int y)
{
  static unsigned short xStack[256];
  static unsigned char yStack[192];
  unsigned char stackentry = 1;
  unsigned char spanAbove, spanBelow;

  unsigned char oldColor = bm_getpixel(x,y);

  if (oldColor == 1)
    return;

  do
    {
      unsigned short startx;
      while (x > 0 && bm_getpixel(x-1,y) == oldColor)
        --x;

      spanAbove = spanBelow = false;
      startx=x;

      while(bm_getpixel(x,y) == oldColor)
        {
          if (y < (191))
            {
              unsigned char belowColor = bm_getpixel(x, y+1);
              if (!spanBelow  && belowColor == oldColor)
                {
                  xStack[stackentry]  = x;
                  yStack[stackentry]  = y+1;
                  ++stackentry;
                  spanBelow = true;
                }
              else if (spanBelow && belowColor != oldColor)
                spanBelow = false;
            }

          if (y > 0)
            {
              unsigned char aboveColor = bm_getpixel(x, y-1);
              if (!spanAbove  && aboveColor == oldColor)
                {
                  xStack[stackentry]  = x;
                  yStack[stackentry]  = y-1;
                  ++stackentry;
                  spanAbove = true;
                }
              else if (spanAbove && aboveColor != oldColor)
                spanAbove = false;
            }

          ++x;
        }
      bm_drawline(startx,y,x-1,y,1);
      --stackentry;
      x = xStack[stackentry];
      y = yStack[stackentry];
    }
  while (stackentry);
}

void main(void)
{
  set_bitmap(0);
  bm_clearscreen();
  bm_setforeground(COLOR_BLACK);

  bm_drawline(100,100,150,100,1);
  bm_drawline(100,100,100,120,1);
  bm_drawline(150,100,150,120,1);
  bm_drawline(100,120,150,120,1);

  paint(149,110);

  for (;;)
    {
    }
}

Attached File  ti_fill_oops.gif   72.07KB   2 downloads

 

-Thom



#2 mindlord OFFLINE  

mindlord

    Star Raider

  • 88 posts

Posted Fri Feb 15, 2019 6:23 PM

There is a slight delay between setting the read address and the VDP actually being ready to be read. Throw an _asm("nop") between setting the vdp read address and the actual read and that might fix it.

Sent from my SM-J727V using Tapatalk

#3 tschak909 OFFLINE  

tschak909

    River Patroller

  • Topic Starter
  • 3,225 posts
  • Location:USA

Posted Fri Feb 15, 2019 6:55 PM

...nope, that didn't work. :(

 

I am obviously misunderstanding something about VDP reads...

 

-Thom



#4 Tursi OFFLINE  

Tursi

    Quadrunner

  • 5,641 posts
  • HarmlessLion
  • Location:BUR

Posted Sat Feb 16, 2019 4:36 PM

There is a slight delay between setting the read address and the VDP actually being ready to be read. Throw an _asm("nop") between setting the vdp read address and the actual read and that might fix it.

Sent from my SM-J727V using Tapatalk


Not necessary on the TI - the CPU is too slow for the delay to have meaning except in very tight assembly code.

One problem you have is that you expect the return of bm_getpixel() to be 0 or 1. It won't be, it will be 0, 1, 2, 4, 8, 16, 32, 64 or 128 (depending on the bit position of the pixel). If you can, just flip your checks around so that you only test against zero instead (faster). Otherwise I'd just change the return to "return (CHECK_BIT(VDPRD,(x% 8))!=0);"

I would also change the return type from char to int. Partially because I still don't 100% trust chars, partially because int is the native word size and your code will be faster for just testing a zero/not zero result against one (no need to mask, shift, pull in additional values, etc). (That would imply making oldcolor an int as well).

It's not clear to be why 'xstack' is a short and 'ystack' is a char... the maximum x value is only 255 anyway?

I think your shift in "CHECK_BIT" is backwards too. If your x modulo is zero, you want the first pixel, which is the MSb (0x80), not 0x01. Start with 0x80 and shift right instead.

I'm not sure that I understand the Y tests inside the while loop in a quick read - but I can tell you that if you pass out-of-range values to bm_getpixel() that you will get random results as you read off screen memory. If it's possible for y to be outside the range 0-191, you want to check that before you call bm_getpixel, else you may get unexpected results. (Like changing register values when you go negative ;) ).

Edited by Tursi, Sat Feb 16, 2019 4:37 PM.


#5 Tursi OFFLINE  

Tursi

    Quadrunner

  • 5,641 posts
  • HarmlessLion
  • Location:BUR

Posted Sat Feb 16, 2019 4:47 PM

Reading a little more, I don't know if the y loop is correct, but it looks like you aren't repeating the x-search per scanline, or searching to the right, which means you'd only fill a rectangle bounded to the right by the starting coordinate, and on the left by the first pixel found. All other rows will use those same x values.

Still, it's probably worth fixing the low hanging fruit before digging deeper. :)

(Removed my floodfill suggestion - there are so many edge cases. There are plenty of solutions already out there.)

Edited by Tursi, Sat Feb 16, 2019 4:51 PM.


#6 tschak909 OFFLINE  

tschak909

    River Patroller

  • Topic Starter
  • 3,225 posts
  • Location:USA

Posted Sat Feb 16, 2019 5:12 PM

*hides-head-in-shame* urgh, I have been carrying around these bits of code for too long now.. they're starting to lose pieces as I carry them from codebase to codebase :P



#7 Tursi OFFLINE  

Tursi

    Quadrunner

  • 5,641 posts
  • HarmlessLion
  • Location:BUR

Posted Sat Feb 16, 2019 9:37 PM

Eh, no biggie. On some systems the leftmost pixel is the MSB on some it's the LSB. Hell, on the Apple it's the /second/ most significant bit. :)




0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users