News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_ervin

Plotting pixels

Started by ervin, 03:59, 29 October 15

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

ervin

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

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;
}

AMSDOS

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?
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

Tai


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

Painting pixels: Introduction to video memory




ronaldo

#3
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 ;).

Fessor

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.

ervin

Thanks for your help everyone!
I'll have a try!
:D


ronaldo

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);
}


TFM

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.  :)
TFM of FutureSoft
Also visit the CPC and Plus users favorite OS: FutureOS - The Revolution on CPC6128 and 6128Plus

ervin

#8
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!

[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;
   }


ronaldo

Correct, @ervin. I mistakenly mixed up both pixel values (didn't properly read my own comments  :laugh: ).

ervin

Quote from: ronaldo on 11:32, 01 November 15
Correct, @ervin. I mistakenly mixed up both pixel values (didn't properly read my own comments  :laugh: ).

Thanks @ronaldo.
I'm glad to know I managed to figure it out.
:)

Powered by SMFPacks Menu Editor Mod