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