cc65: Atari: Setting pixel data 10x slower than before
This is a strange bug, probably one for Chris Groessler! 😃
I have been using a 2018 version of CC65 for a while, and decided to upgrade to latest for next release of 8bit-Unity. Most functions work normally (such as loading bitmaps), but one function for setting pixels has become incredibly slow. The code is as follows (compiled using default atarixl.cfg):
#define BITMAPRAM1 (0x7010) // 7010-8f50 (bitmap frame 1)
#define BITMAPRAM2 (0xa010) // a010-bf50 (bitmap frame 2)
void SetPixel(unsigned int pixelX, unsigned int pixelY, unsigned char color)
{
unsigned int offset;
unsigned char shift, mask, col1, col2;
// Compute pixel location
offset = 40*pixelY + pixelX/4;
shift = 6 - 2*(pixelX%4);
mask = 255 - (3 << shift);
if ((pixelY+pixelX)%2) {
col2 = (color%4) << shift;
col1 = (color/4) << shift;
} else {
col1 = (color%4) << shift;
col2 = (color/4) << shift;
}
// Set color/color2 in dual buffer
POKE((char*)BITMAPRAM1+offset, (PEEK((char*)BITMAPRAM1+offset) & mask) | col1);
POKE((char*)BITMAPRAM2+offset, (PEEK((char*)BITMAPRAM2+offset) & mask) | col2);
}
I wonder if the system is waiting for a VSYNC or something, whenever I touch the bitmap ram?
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 40 (31 by maintainers)
Commits related to this issue
- Adjust type of int constants that fit in char When there is an integral constant like `3` in an expression, it has type `int` according to the C spec, even though it can be represented as an `unsigne... — committed to jmr/cc65 by jmr 4 years ago
- Adjust type of int constants that fit in char When there is an integral constant like `3` in an expression, it has type `int` according to the C spec, even though it can be represented as an `unsigne... — committed to cc65/cc65 by jmr 4 years ago
Use
It does the same thing, but no
clc. It’s only one byte smaller and two cycles faster, but every little bit helps!With 060417b0dc1018adc79fd16d0eb97c61d729aea3 ‘mul40’ and two small tables I’m down to 45 on the Atari.
Maybe it’s just me, but in general I would choose a table driven approach for the shifts and the 4 colours…
Here’s the main difference with #1328:
I don’t think this can be easily fixed since
pixelY + pixelXhas typeinteven though both operands areunsigned char. I could imagine some analysis that0 <= pixelY + pixelX <= 2 * 255. Therefore, we could do an unsigned mod rather than a signed one. I’m not sure how hard that is, but it could be worth thinking about.Changing
(pixelY+pixelX)%2to(pixelY+pixelX)%2Urestores the old performance (along with #1328). The rest of the code can remain the same.