CPCWiki forum

General Category => Programming => Topic started by: ervin on 03:59, 29 October 15

Title: Plotting pixels
Post by: ervin on 03:59, 29 October 15
Hi folks.

I'm trying to figure out how to paint pixels in mode 1 and mode 2, by modifying the mode 0 routines found on cpcmania.com.
SDCC vs z88dk: Comparing size and speed (http://www.cpcmania.com/Docs/Programming/SDCC_vs_z88dk_Comparing_size_and_speed.htm)

Can someone please suggest what I'd need to do to the 2 functions below?
Ideally, I'd like mode 1 and mode 2 versions of each function.
I just can't figure it out!
:'(

Thanks for any help.


void PutPixelMode0(unsigned char nX, unsigned char nY, unsigned char nColor)
{
  unsigned char nPixel = 0;
  unsigned int nAddress = 0xC000 + ((nY / 8) * 80) + ((nY % 8) * 2048) + (nX / 2);
  nPixel = nX % 2;

  SetMode0PixelColor((unsigned char *)nAddress, nColor, nPixel);
}

void SetMode0PixelColor(unsigned char *pByteAddress, unsigned char nColor, unsigned char nPixel)
{
  unsigned char nByte = *pByteAddress;

  if(nPixel == 0)
  {
    nByte &= 85;

    if(nColor & 1)
      nByte |= 128;

    if(nColor & 2)
      nByte |= 8;

    if(nColor & 4)
      nByte |= 32;

    if(nColor & 8)
      nByte |= 2;
  }
  else
  {
    nByte &= 170;

    if(nColor & 1)
      nByte |= 64;

    if(nColor & 2)
      nByte |= 4;

    if(nColor & 4)
      nByte |= 16;

    if(nColor & 8)
      nByte |= 1;
  }

  *pByteAddress = nByte;
}
Title: Re: Plotting pixels
Post by: AMSDOS on 09:19, 29 October 15
So in Mode 0 a Byte has a Left Most Pixel & a Right Most Pixel along the Xpos line, so perhaps where it reads "nX / 2" needs to be changed to "nX / 4" for Mode 1 and "nX / 8" for Mode 2. That nPixel line may need to change as well to have those multiples, though I may have that wrong.


SetMode0PixelColor is doing some sort of check with those Left Most Pixels & Right Most Pixels, but there's 4 colour groups, I'm not too sure what's going on there, some sort of Alternative Ink colour switch?
Title: Re: Plotting pixels
Post by: Tai on 10:58, 29 October 15

You can check here how pixels are arranged in a byte for each video mode.

Painting pixels: Introduction to video memory (http://www.cpcmania.com/Docs/Programming/Painting_pixels_introduction_to_video_memory.htm)



Title: Re: Plotting pixels
Post by: ronaldo on 11:07, 29 October 15
Assuming you have X, Y coordinates in pixels, you only have to write your pixels, codified in screen pixel format, directly to memory:

u8* pvmem;
pvmem = cpct_getScreenPtr((u8*)0xC000, x / 2, y);

// For mode 0
*pvmem = cpct_px2byteM0 (color_pixel_1, color_pixel_2);

// For mode 1
*pvmem = cpct_px2byteM1 (color_pixel_1, color_pixel_2, color_pixel_3, color_pixel_4);

And that's it :) .

Also, for your reference, screen pixel format is described in cpct_px2byteM0 documentation (http://lronaldo.github.io/cpctelera/files/sprites/cpct_px2byteM0-asm.html) ;).
Title: Re: Plotting pixels
Post by: Fessor on 11:11, 29 October 15
What the Routine do is:
It gets the byte from the Screen-Memory, saves with &= 85 (&x0101010) / &= 170 (&x10101010) the color of the other Pixel and also cleans the bits for the pixelcolor to be set and looks with bit is set at the Pen-Number and then sets the corresponding bit for the screen-memory-format. The result is written back to Memory.

nbyte &= 85 means nbyte = nbyte AND 85. The percent stands for a Modulo-Operation. For Mode 1 nPixel = nX % 4 (for four Pixel per Byte), Mode 2 nPixel = nX % 8 (for 8 Pixel per Byte)

For Mode 1 the Bitmaps of the three other Pixels have to be saved so you need four ifs for the four pixel-positions, and 4 masks to save the other pixels. For Mode 2 eight ifs for each Pixelposition in the Byte and 8 Masks to save the other Pixels.
Title: Re: Plotting pixels
Post by: ervin on 11:18, 29 October 15
Thanks for your help everyone!
I'll have a try!
:D

Title: Re: Plotting pixels
Post by: ronaldo on 14:30, 29 October 15
Also, if you wanted to pring a single pixel, mixing it with actual contents of video memory, I'd do this (Warning! Untested code!):

#define M0_PIXEL1_MASK 0xAA
#define M0_PIXEL2_MASK 0x55

//         x,y: pixel coordinates in pixels
// pixel_color: PEN color for the pixel to be lightened
//
void putpixel(u8 x, u8 y, u8 pixel_color) {
   u8* pvmem, pix1 = 0, pix2 = 0;
 
   // Get a pointer to the byte where the pixel is
   pvmem = cpct_getScreenPtr((u8*)0xC000, x / 2, y);

   // Check if pixel is even (pixel 1) or odd (pixel 2)
   if (x & 1) {
      // Odd pixel = Pixel 2 = Right pixel of the byte
      // Even pixel will stay, Odd pixel have to be removed
      *pvmem &= M0_PIXEL1_MASK;
      pix1    = pixel_color;
   } else {
      // Even pixel = Pixel 1 = Left pixel of the byte
      // Odd pixel will stay, Even pixel have to be removed
      *pvmem &= M0_PIXEL2_MASK;
      pix2    = pixel_color;
   }

   // Set the color of the pixel
   *pvmem |= cpct_px2byteM0 (pix1, pix2);
}

Title: Re: Plotting pixels
Post by: TFM on 18:09, 29 October 15
IMHO the best thing is to have totally separated PLOT routines for MODE 0-3. They are worlds apart. MODE 2 can be very quick.


Please take a look at my FIOLIB, you will find quick routines there.  :)
Title: Re: Plotting pixels
Post by: ervin on 23:24, 29 October 15
Quote from: ronaldo on 14:30, 29 October 15
Also, if you wanted to pring a single pixel, mixing it with actual contents of video memory, I'd do this (Warning! Untested code!):

#define M0_PIXEL1_MASK 0xAA
#define M0_PIXEL2_MASK 0x55

//         x,y: pixel coordinates in pixels
// pixel_color: PEN color for the pixel to be lightened
//
void putpixel(u8 x, u8 y, u8 pixel_color) {
   u8* pvmem, pix1 = 0, pix2 = 0;
 
   // Get a pointer to the byte where the pixel is
   pvmem = cpct_getScreenPtr((u8*)0xC000, x / 2, y);

   // Check if pixel is even (pixel 1) or odd (pixel 2)
   if (x & 1) {
      // Odd pixel = Pixel 2 = Right pixel of the byte
      // Even pixel will stay, Odd pixel have to be removed
      *pvmem &= M0_PIXEL1_MASK;
      pix1    = pixel_color;
   } else {
      // Even pixel = Pixel 1 = Left pixel of the byte
      // Odd pixel will stay, Even pixel have to be removed
      *pvmem &= M0_PIXEL2_MASK;
      pix2    = pixel_color;
   }

   // Set the color of the pixel
   *pvmem |= cpct_px2byteM0 (pix1, pix2);
}


That's fantastic, thanks @ronaldo (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1227)!

[EDIT] I got it working! But only after I swapped pix1 and pix2 in the IF block.


   if (x & 1) {
      // Odd pixel = Pixel 2 = Right pixel of the byte
      // Even pixel will stay, Odd pixel have to be removed
      *pvmem &= M0_PIXEL1_MASK;
      pix2    = pixel_color;
   } else {
      // Even pixel = Pixel 1 = Left pixel of the byte
      // Odd pixel will stay, Even pixel have to be removed
      *pvmem &= M0_PIXEL2_MASK;
      pix1    = pixel_color;
   }

Title: Re: Plotting pixels
Post by: ronaldo on 11:32, 01 November 15
Correct, @ervin (http://www.cpcwiki.eu/forum/index.php?action=profile;u=82). I mistakenly mixed up both pixel values (didn't properly read my own comments  :laugh: ).
Title: Re: Plotting pixels
Post by: ervin on 12:45, 01 November 15
Quote from: ronaldo on 11:32, 01 November 15
Correct, @ervin (http://www.cpcwiki.eu/forum/index.php?action=profile;u=82). I mistakenly mixed up both pixel values (didn't properly read my own comments  :laugh: ).

Thanks @ronaldo (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1227).
I'm glad to know I managed to figure it out.
:)
Powered by SMFPacks Menu Editor Mod