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;
}
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?
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)
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) ;).
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.
Thanks for your help everyone!
I'll have a try!
:D
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);
}
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. :)
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;
}
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: ).
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.
:)