387 lines
9.9 KiB
C
387 lines
9.9 KiB
C
void BlitFirstPlaneFirstRowToSecondRow(struct ScreenSetup *screenSetup) {
|
|
unsigned char *source = screenSetup->memoryStart;
|
|
unsigned char *target = (screenSetup->memoryStart + SCREEN_WIDTH * 2 / 8);
|
|
|
|
custom.bltcon0 = 0x09f0;
|
|
custom.bltcon1 = 0;
|
|
custom.bltapt = source;
|
|
custom.bltdpt = target;
|
|
custom.bltamod = 0;
|
|
custom.bltdmod = 0;
|
|
custom.bltafwm = 0xffff;
|
|
custom.bltalwm = 0xffff;
|
|
custom.bltsize = 0x0041;
|
|
}
|
|
|
|
void BlitShiftFirstPlaneFirstRowToThirdRow(struct ScreenSetup *screenSetup) {
|
|
unsigned char *source = screenSetup->memoryStart;
|
|
unsigned char *target = (screenSetup->memoryStart + SCREEN_WIDTH * 4 / 8);
|
|
|
|
custom.bltcon0 = 0x49f0;
|
|
custom.bltcon1 = 0;
|
|
custom.bltapt = source;
|
|
custom.bltdpt = target;
|
|
custom.bltamod = 0;
|
|
custom.bltdmod = 0;
|
|
custom.bltafwm = 0xffff;
|
|
custom.bltalwm = 0xffff;
|
|
custom.bltsize = 0x0041;
|
|
}
|
|
|
|
void BlitWithMaskInBChannel(struct ScreenSetup *screenSetup) {
|
|
unsigned char *source = screenSetup->memoryStart;
|
|
unsigned char *target = (screenSetup->memoryStart + SCREEN_WIDTH * 6 / 8);
|
|
unsigned char *mask = (screenSetup->memoryStart + 8);
|
|
|
|
// a is source
|
|
// b is mask
|
|
// d is destination
|
|
|
|
// so I want AB
|
|
|
|
custom.bltcon0 = 0x0dc0;
|
|
custom.bltcon1 = 0;
|
|
custom.bltapt = mask;
|
|
custom.bltbpt = source;
|
|
custom.bltdpt = target;
|
|
custom.bltamod = 0;
|
|
custom.bltdmod = 0;
|
|
custom.bltafwm = 0xffff;
|
|
custom.bltalwm = 0xffff;
|
|
custom.bltsize = 0x0041;
|
|
}
|
|
|
|
void BlitWithMaskInBDataInCChannel(struct ScreenSetup *screenSetup) {
|
|
unsigned char *source = screenSetup->memoryStart;
|
|
unsigned char *target = (screenSetup->memoryStart + SCREEN_WIDTH * 8 / 8);
|
|
unsigned char *mask = (screenSetup->memoryStart + 8);
|
|
unsigned char *background = (screenSetup->memoryStart + 16);
|
|
|
|
// a is source
|
|
// b is mask
|
|
// c is background
|
|
// d is destination
|
|
|
|
// so I want AB+`AC
|
|
|
|
custom.bltcon0 = 0x0fca;
|
|
custom.bltcon1 = 0;
|
|
custom.bltapt = mask;
|
|
custom.bltbpt = source;
|
|
custom.bltcpt = background;
|
|
custom.bltdpt = target;
|
|
custom.bltamod = 0;
|
|
custom.bltbmod = 0;
|
|
custom.bltcmod = SCREEN_WIDTH / 8;
|
|
custom.bltdmod = SCREEN_WIDTH / 8;
|
|
custom.bltafwm = 0xffff;
|
|
custom.bltalwm = 0xffff;
|
|
custom.bltsize = 0x0041;
|
|
}
|
|
|
|
void BlitDrawHorizontalLine(struct ScreenSetup *screenSetup) {
|
|
|
|
// i want to draw a line from 20,20 to 50,80
|
|
// i need to get dx and dy
|
|
// dx is 30, dy is 60
|
|
// the shift value is 20 mod 15 = 5
|
|
// a data register gets $8000
|
|
// b data register gets $ffff
|
|
// text shift is 0
|
|
// c and d pointers get the word containing the first pixel, so
|
|
// screenSetup->memoryStart + 320 * 20 / 8 + 2
|
|
// module registers get width of bitplane in bytes
|
|
// blit height is dx + 1 so 31
|
|
// blit width = 2
|
|
// logic is ab+'a, so 6, 7, 2, 3, 1, 0
|
|
|
|
char *target = screenSetup->memoryStart + (320 * 20 + 20) / 8;
|
|
int dx = 10;
|
|
int dy = 60;
|
|
int tmp;
|
|
|
|
if (dx < dy) {
|
|
tmp = dx;
|
|
dx = dy;
|
|
dy = tmp;
|
|
}
|
|
|
|
custom.bltcon0 = (5 << 12) + (11 << 8) + 0xca;
|
|
custom.bltcon1 = 1;
|
|
custom.bltapt = 4 * dy - 2 * dx;
|
|
custom.bltadat = 0x8000;
|
|
custom.bltbdat = 0xffff;
|
|
custom.bltcpt = target;
|
|
custom.bltdpt = target;
|
|
custom.bltamod = 4 * (dy - dx);
|
|
custom.bltbmod = 4 * dy;
|
|
custom.bltcmod = 320 / 8;
|
|
custom.bltdmod = 320 / 8;
|
|
custom.bltafwm = 0xffff;
|
|
custom.bltalwm = 0xffff;
|
|
custom.bltsize = 0x02 + (dx + 1 << 7);
|
|
}
|
|
|
|
|
|
void blit_buildGenericBlitData(
|
|
struct BlitAreaDetails *source,
|
|
struct BlitGenericData *data,
|
|
uint16_t sx,
|
|
uint16_t sy,
|
|
uint16_t ex,
|
|
uint16_t ey,
|
|
uint16_t tx,
|
|
uint16_t ty
|
|
) {
|
|
int8_t shift = (sx & 0xfff0) - sx + (tx & 15);
|
|
|
|
uint8_t needsDescending = shift < 0;
|
|
|
|
uint8_t i;
|
|
|
|
uint8_t firstWordPixelMask;
|
|
uint8_t lastWordPixelMask;
|
|
|
|
uint16_t firstWordMask = 0xFFFF;
|
|
uint16_t lastWordMask = 0xFFFF;
|
|
|
|
uint16_t wordSource, wordTarget;
|
|
uint16_t heightStart;
|
|
uint16_t targetHeightStart;
|
|
|
|
// this is correct, there will always be at least two bytes
|
|
uint16_t width = WORD_ALIGNED_BYTE_X(ex - sx + abs(shift)) + 2;
|
|
|
|
uint16_t height = ey;
|
|
|
|
//printf("%d %d %d\n", wordStart, wordEnd, width);
|
|
|
|
data->shift = shift;
|
|
data->width = width;
|
|
data->height = height;
|
|
|
|
firstWordMask = 0x0000;
|
|
lastWordMask = 0x0000;
|
|
|
|
if (needsDescending) {
|
|
wordSource = WORD_ALIGNED_BYTE_X(sx) + width - 2;
|
|
wordTarget = WORD_ALIGNED_BYTE_X(tx) + width - 2;
|
|
heightStart = WORD_ALIGNED_BYTE_X(source->drawAreaWidth * ey);
|
|
targetHeightStart = WORD_ALIGNED_BYTE_X(source->drawAreaWidth * (ty + height));
|
|
|
|
// this needs to be more precise
|
|
// using x positions and not this niave approach
|
|
firstWordPixelMask = (ex & 15) + 1;
|
|
lastWordPixelMask = 16 - (sx & 15);
|
|
|
|
for (i = 0; i < lastWordPixelMask; ++i) {
|
|
uint16_t bit = (1 << i);
|
|
|
|
lastWordMask += bit;
|
|
}
|
|
|
|
for (i = 0; i < firstWordPixelMask; ++i) {
|
|
uint16_t bit = (1 << (15 - i));
|
|
|
|
firstWordMask += bit;
|
|
}
|
|
} else {
|
|
wordSource = WORD_ALIGNED_BYTE_X(sx);
|
|
wordTarget = WORD_ALIGNED_BYTE_X(tx);
|
|
heightStart = WORD_ALIGNED_BYTE_X(0);
|
|
targetHeightStart = WORD_ALIGNED_BYTE_X(source->drawAreaWidth * ty);
|
|
|
|
firstWordPixelMask = 16 - (sx & 15);
|
|
lastWordPixelMask = (ex & 15) + 1 - shift;
|
|
|
|
for (i = 0; i < firstWordPixelMask; ++i) {
|
|
uint16_t bit = (1 << i);
|
|
|
|
firstWordMask += bit;
|
|
}
|
|
|
|
for (i = 0; i < lastWordPixelMask; ++i) {
|
|
uint16_t bit = (1 << (15 - i));
|
|
|
|
lastWordMask += bit;
|
|
}
|
|
}
|
|
|
|
data->heightStart = heightStart;
|
|
data->targetHeightStart = targetHeightStart;
|
|
data->wordSource = wordSource;
|
|
data->wordTarget = wordTarget;
|
|
data->firstWordMask = firstWordMask;
|
|
data->lastWordMask = lastWordMask;
|
|
}
|
|
|
|
void blit_generic(
|
|
struct BlitAreaDetails *source,
|
|
struct BlitGenericData *blitGenericData,
|
|
uint16_t sx,
|
|
uint16_t sy,
|
|
uint16_t ex,
|
|
uint16_t ey,
|
|
uint16_t tx,
|
|
uint16_t ty
|
|
) {
|
|
uint8_t needsDescending;
|
|
|
|
blit_buildGenericBlitData(
|
|
source,
|
|
blitGenericData,
|
|
sx, sy, ex, ey, tx, ty
|
|
);
|
|
|
|
needsDescending = blitGenericData->shift < 0;
|
|
|
|
custom.bltcon0 = 0xF0 + (1 << 8) + (1 << 11) + (abs(blitGenericData->shift) << 12);
|
|
custom.bltcon1 = (needsDescending << 1);
|
|
|
|
custom.bltadat = 0xFFFF;
|
|
|
|
custom.bltafwm = blitGenericData->firstWordMask;
|
|
custom.bltalwm = blitGenericData->lastWordMask;
|
|
|
|
custom.bltapt = source->target + blitGenericData->heightStart + blitGenericData->wordSource;
|
|
custom.bltdpt = source->target + blitGenericData->targetHeightStart + blitGenericData->wordTarget;
|
|
|
|
custom.bltamod = source->drawAreaWidth / 8 - blitGenericData->width;
|
|
custom.bltdmod = source->drawAreaWidth / 8 - blitGenericData->width;
|
|
|
|
custom.bltsize = (blitGenericData->width / 2) + ((blitGenericData->height + 1) << 6);
|
|
|
|
WaitBlit();
|
|
}
|
|
|
|
void blit_fillAreaDetailsFromScreenSetup(
|
|
struct ScreenSetup *screenSetup,
|
|
struct BlitAreaDetails *blitAreaDetails
|
|
) {
|
|
blitAreaDetails->target = screenSetup->memoryStart;
|
|
blitAreaDetails->drawAreaWidth = screenSetup->width;
|
|
blitAreaDetails->nextBitplaneAdvance = screenSetup->nextBitplaneAdvance;
|
|
blitAreaDetails->contiguousBitplanes = screenSetup->bitplanes;
|
|
}
|
|
|
|
|
|
void blit_copyOneToOne(
|
|
struct BlitAreaDetails *source,
|
|
struct BlitAreaDetails *target,
|
|
uint16_t sx,
|
|
uint16_t sy,
|
|
uint16_t ex,
|
|
uint16_t ey,
|
|
uint16_t tx,
|
|
uint16_t ty
|
|
) {
|
|
uint16_t dx = ex - sx;
|
|
uint16_t dy = ey - sy;
|
|
|
|
// 23 = 2
|
|
// 24 = 3
|
|
// 0-15 has to equal 2
|
|
// 16-31 has to equal 4
|
|
//
|
|
// 23 = ((23 / 8) & fffe) + 2 =
|
|
uint16_t aModulo = (source->drawAreaWidth / 8) - (((dx + 16) >> 3) & 0xfffe);
|
|
uint16_t dModulo = (target->drawAreaWidth / 8) - (((dx + 16) >> 3) & 0xfffe);
|
|
|
|
uint8_t shiftA = sx % 16;
|
|
|
|
unsigned char *aPointer = source->target + WORD_ALIGNED_BYTE_POSITION(source->drawAreaWidth, sx, sy);
|
|
unsigned char *dPointer = target->target + WORD_ALIGNED_BYTE_POSITION(target->drawAreaWidth, tx, ty);
|
|
|
|
custom.bltcon0 = (1 << 11) + (1 << 8) + 0xca;
|
|
custom.bltcon1 = (1 << 1);
|
|
//custom.bltapt = aPointer;
|
|
//custom.bltdpt = dPointer;
|
|
|
|
custom.bltapt = aPointer + WORD_ALIGNED_BYTE_POSITION(source->drawAreaWidth, dx, dy);
|
|
custom.bltdpt = dPointer + WORD_ALIGNED_BYTE_POSITION(target->drawAreaWidth, dx, dy);
|
|
|
|
custom.bltamod = aModulo;
|
|
custom.bltdmod = dModulo;
|
|
custom.bltafwm = 0xffff;
|
|
custom.bltalwm = 0xffff;
|
|
|
|
custom.bltsize = (dx / 16) + 1 + (dy << 6);
|
|
}
|
|
|
|
void blit_howDoesFWMandLWMWork(
|
|
struct BlitAreaDetails *source,
|
|
struct BlitAreaDetails *target
|
|
) {
|
|
// goal: shift over one pixel to right
|
|
// width: 32px + 1px shift = 33 = 3 words
|
|
// fw mask = 0xffff -- copy everything
|
|
// lw mask = 0x0000 -- do not copy anything
|
|
|
|
// enable a, b, and c
|
|
custom.bltcon0 = 0xF0 + (1 << 8) + (1 << 11) + (1 << 12);
|
|
custom.bltcon1 = 0;
|
|
|
|
custom.bltadat = 0xffff;
|
|
custom.bltafwm = 0xffff;
|
|
custom.bltalwm = 0x0000;
|
|
|
|
custom.bltapt = source->target;
|
|
custom.bltdpt = target->target + 40;
|
|
|
|
custom.bltamod = source->drawAreaWidth ;
|
|
custom.bltbmod = target->drawAreaWidth;
|
|
|
|
custom.bltsize = (3) + (1 << 6);
|
|
|
|
WaitBlit();
|
|
|
|
// this will need to go in reverse so i can shift left
|
|
custom.bltcon0 = 0xF0 + (1 << 8) + (1 << 11) + (1 << 12);
|
|
custom.bltcon1 = (1 << 1);
|
|
|
|
custom.bltadat = 0x0000;
|
|
custom.bltafwm = 0xffff;
|
|
custom.bltalwm = 0x0000;
|
|
|
|
custom.bltapt = source->target + 10 + 2;
|
|
custom.bltdpt = target->target + 40 + 10 + 2;
|
|
|
|
custom.bltamod = source->drawAreaWidth;
|
|
custom.bltdmod = target->drawAreaWidth;
|
|
|
|
custom.bltsize = (3) + (1 << 6);
|
|
WaitBlit();
|
|
|
|
|
|
}
|
|
|
|
// TODO: blit_drawRectangle
|
|
void blit_clearScreen(struct ScreenSetup *screenSetup, int color) {
|
|
unsigned char *target = screenSetup->memoryStart;
|
|
int i;
|
|
|
|
// a is source
|
|
// b is mask
|
|
// c is background
|
|
// d is destination
|
|
|
|
// so I want AB+`AC
|
|
|
|
custom.bltcon0 = (0x01 << 8) + 0xf0;
|
|
custom.bltcon1 = 0;
|
|
custom.bltamod = 0;
|
|
custom.bltdmod = 0;
|
|
custom.bltafwm = 0xffff;
|
|
custom.bltalwm = 0xffff;
|
|
|
|
for (i = 0; i < screenSetup->bitplanes; ++i) {
|
|
custom.bltadat = color & 1 == 1 ? 0xffff : 0;
|
|
custom.bltdpt = target + (320 * 256 / 8) * i;
|
|
custom.bltsize = (256 << 7) + (320 / 8);
|
|
myWaitBlit();
|
|
|
|
color >>= 1;
|
|
}
|
|
}
|
|
|