//////////////////////////////////////////////////////////////////////
// Davr's sketching test
// based off of libnds examples
// line code ripped from darkain's darkstar
// april 2006
//////////////////////////////////////////////////////////////////////

#include <nds.h>

#include <nds/arm9/console.h> //basic print funcionality
#include <stdlib.h>
#include <stdio.h>


void WaitForVblank()
{
	while(DISP_Y!=192);
	while(DISP_Y==192);
}
void line(u8 *buf, s16 x1, s16 y1, s16 x2, s16 y2, u8 color, u8 size);

int main(void)
{
    powerSET(POWER_ALL_2D);
    //set the mode for 2 text layers and two extended background layers
	videoSetMode(MODE_5_2D | DISPLAY_BG3_ACTIVE); 
	
	//set the sub background up for text display (we could just print to one
	//of the main display text backgrounds just as easily
	videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE); //sub bg 0 will be used to print text
	
    //set the first two banks as background memory and the third as sub background memory
    //D is not used..if you need a bigger background then you will need to map
    //more vram banks consecutivly (VRAM A-D are all 0x20000 bytes in size)
    vramSetMainBanks(VRAM_A_MAIN_BG_0x6000000, VRAM_B_MAIN_BG_0x6020000, 
                     VRAM_C_SUB_BG , VRAM_D_LCD); 

	////////////////set up text background for text/////////////////////
    SUB_BG0_CR = BG_MAP_BASE(31);
	
	BG_PALETTE_SUB[255] = RGB15(31,31,31);//by default font will be rendered with color 255
	
	//consoleInit() is a lot more flexible but this gets you up and running quick
	consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(31), (u16*)CHAR_BASE_BLOCK_SUB(0), 16);

	iprintf("\n\n\tDrawing Test\n");
	iprintf("\twww.davr.org\n");
	iprintf("\tDavid R");
	
	///////////////set up our bitmap background///////////////////////
	
	BG3_CR = BG_BMP16_256x256;
	
	//these are rotation backgrounds so you must set the rotation attributes:
    //these are fixed point numbers with the low 8 bits the fractional part
    //this basicaly gives it a 1:1 translation in x and y so you get a nice flat bitmap
        BG3_XDX = 1 << 8;
        BG3_XDY = 0;
        BG3_YDX = 0;
        BG3_YDY = 1 << 8;
    //our bitmap looks a bit better if we center it so scroll down (256 - 192) / 2 
        BG3_CX = 0;
        BG3_CY = 0;
        
    
	u16* frontBuffer = (u16*)(0x06000000);
	u16* backBuffer =  (u16*)(0x06000000 + 256 * 256 * 2);

        u8* img = (u8 *)0x02200000; //(u8 *)malloc(512*384);

        iprintf("\nImage stored at: 0x%X\n\n", img);
        iprintf("A to clear\nUP to make line thicker\nDOWN to make line thinner");
	
        int x1=0,y1=0,x2=0,y2=0;

        touchPosition touchXY, touchXY2, touchXY3;

        for(int y=0;y<384;y++)
        {
            for(int x=0;x<512;x++)
            {
                img[y*512 + x] = 31;
            }
        }

    u8 safety = 0;
    u8 size = 1;

    u8 frame = 0;
	
    while(1)
    {
        //draw a box
//        for(int iy = 60; iy < 196 - 60; iy++)
  //          for(int ix = 60; ix < 256 - 60; ix++)
    //            backBuffer[iy * 256 + ix] = (rand() & colorMask) | BIT(15);
    
        if(frame < 4)
        {

        //for(int y=0;y<382;y+=2)
        for(int y=96*frame;y<96*(frame+1);y+=2)
            for(int x=0;x<510;x+=2)
            {
                u16 c1 = img[y*512 + x];
                u16 c2 = img[y*512 + x + 1];
                u16 c3 = img[y*512 + x + 512];
                u16 c4 = img[y*512 + x + 512 + 1];
                u16 c = (c1+c2+c3+c4) / 4;
                backBuffer[(y/2)*256 + (x/2)] = RGB15(c,c,c) | BIT(15);
            }
        }
        
        frame++;
        if(frame >= 5)
            frame = 0;
                
        scanKeys();
        int keys = keysHeld();
        int down = keysDown();
        if(keys & KEY_TOUCH)
        {
            touchXY=touchReadXY();
            safety++;
            if(!(down & KEY_TOUCH) && safety > 2)
            {
                line(img, touchXY3.px*2,touchXY3.py*2,touchXY2.px*2,touchXY2.py*2,0, size);
            }
            touchXY3 = touchXY2;
            touchXY2 = touchXY;
        }
        else
        {
            safety = 0;
        }

        if(down & KEY_A)
        {
            for(int y=0;y<384;y++)
            {
                for(int x=0;x<512;x++)
                {
                    img[y*512 + x] = 31;
                }
            }
        }

        if(down & KEY_UP)
        {
            size++;
            if(size > 5)
                size = 5;
        }
        if(down & KEY_DOWN)
        {
            size--;
            if(size < 1)
                size = 1;
        }




        WaitForVblank();

        
        //swap
        u16* temp = frontBuffer;
        frontBuffer = backBuffer;
        backBuffer = temp;
        
        //flip 
        //base is 16KB and screen size is 256x256x2 (128KB)
        BG3_CR ^= BG_BMP_BASE( 128 / 16 );

        // /x1b[line;columnH
        iprintf("\x1b[16;4HLine Size:%d  ",size);
        
        
    }
	return 0;
}

#define setPixelA(x,y,c) (buf[((y)*512) + (x)] = c);

void line(u8 *buf, s16 x1, s16 y1, s16 x2, s16 y2, u8 color, u8 size) { 

  s32 deltax = abs(x2 - x1);    // The difference between the x's
  s32 deltay = abs(y2 - y1);    // The difference between the y's
  s32 x = x1;                   // Start x off at the first pixel
  s32 y = y1;                   // Start y off at the first pixel

  s32 xinc1, xinc2, yinc1, yinc2;
  s32 den, num, numadd, numpixels;

  if (x2 >= x1) {               // The x-values are increasing
    xinc1 = 1;
    xinc2 = 1;
  } else {                      // The x-values are decreasing
    xinc1 = -1;
    xinc2 = -1;
  }

  if (y2 >= y1) {               // The y-values are increasing
    yinc1 = 1;
    yinc2 = 1;
  } else {                      // The y-values are decreasing
    yinc1 = -1;
    yinc2 = -1;
  }

  if (deltax >= deltay) {       // There is at least one x-value for every y-value
//    xinc1 = 0;                  // Don't change the x when numerator >= denominator
//    yinc2 = 0;                  // Don't change the y for every iteration
    den = deltax;
    num = deltax >> 1;
    numadd = deltay;
    numpixels = deltax;         // There are more x-values than y-values

    for (s32 curpixel = 0; curpixel <= numpixels; curpixel++) {
      setPixelA(x, y, color);     // Draw the current pixel
      if(size>1) setPixelA(x, y+1, color);     // Draw the current pixel
      if(size>2) setPixelA(x, y-1, color);     // Draw the current pixel
      if(size>3) setPixelA(x, y+2, color);     // Draw the current pixel
      if(size>4) setPixelA(x, y-2, color);     // Draw the current pixel

      num += numadd;              // Increase the numerator by the top of the fraction
      if (num >= den) {           // Check if numerator >= denominator
        num -= den;               // Calculate the new numerator value
//        x += xinc1;               // Change the x as appropriate
        y += yinc1;               // Change the y as appropriate
      }
      x += xinc2;                 // Change the x as appropriate
//      y += yinc2;                 // Change the y as appropriate
    }


  } else {                      // There is at least one y-value for every x-value
//    xinc2 = 0;                  // Don't change the x for every iteration
//    yinc1 = 0;                  // Don't change the y when numerator >= denominator
    den = deltay;
    num = deltay >> 1;
    numadd = deltax;
    numpixels = deltay;         // There are more y-values than x-values

    for (s32 curpixel = 0; curpixel <= numpixels; curpixel++) {
      setPixelA(x, y, color);     // Draw the current pixel
      if(size>1) setPixelA(x+1, y, color);     // Draw the current pixel
      if(size>2) setPixelA(x-1, y, color);     // Draw the current pixel
      if(size>3) setPixelA(x+2, y, color);     // Draw the current pixel
      if(size>4) setPixelA(x-2, y, color);     // Draw the current pixel

      num += numadd;              // Increase the numerator by the top of the fraction
      if (num >= den) {           // Check if numerator >= denominator
        num -= den;               // Calculate the new numerator value
        x += xinc1;               // Change the x as appropriate
//        y += yinc1;               // Change the y as appropriate
      }
//      x += xinc2;                 // Change the x as appropriate
      y += yinc2;                 // Change the y as appropriate
    }

  }
/*
  for (s32 curpixel = 0; curpixel <= numpixels; curpixel++) {
    setPixelA(x, y, color);     // Draw the current pixel
    num += numadd;              // Increase the numerator by the top of the fraction
    if (num >= den) {           // Check if numerator >= denominator
      num -= den;               // Calculate the new numerator value
      x += xinc1;               // Change the x as appropriate
      y += yinc1;               // Change the y as appropriate
    }
    x += xinc2;                 // Change the x as appropriate
    y += yinc2;                 // Change the y as appropriate
  }
*/
}


