#include #include #include #include #include #include #include #include #include "system/blitter.h" #include "system/copper.h" #include "system/system.h" #include "screen.h" #include "types.h" #include "bun.h" extern struct Custom far custom; extern struct CIA far ciaa; // this should be large enough to hold one bitplane of the largest object // you are blitting, plus one additional word on each side #define SCRATCH_AREA_WIDTH_BYTES (8) #define SCRATCH_AREA_HEIGHT_ROWS (34) #define SCRATCH_AREA_MEMORY_SIZE (SCRATCH_AREA_WIDTH_BYTES * SCRATCH_AREA_HEIGHT_ROWS) volatile short *dbg = (volatile short *)0x100; unsigned char *scratchArea; struct ScreenSetup screenSetup; struct CurrentScreen currentScreen; void *copperlistBitplanePointers[8][2]; void *copperlistSpritePointers[8]; #define offsetof(s, m) &((struct s *)0)->m uint16_t custom_color = (uint16_t)offsetof(Custom, color); uint16_t custom_sprite = (uint16_t)offsetof(Custom, sprpt); uint16_t custom_sprite_control = (uint16_t)offsetof(Custom, spr); #define SPRPOS(x, y) (((y & 0xff) << 8) + ((x & 0x1fe) >> 1)) #define SPRCTL(x, y, height) ( \ ((height & 0xff) << 8) + \ ((y & 0x100) >> 6) + \ ((height & 0x100) >> 7) + \ (x & 1) \ ) extern uint8_t chip TopazBitplanes[]; extern uint16_t chip CopperColors[]; extern uint16_t chip SpriteCopperlist[]; extern uint16_t chip SpriteData[]; extern uint8_t chip MaskBitplane[]; #define TOPAZ_WIDTH_PIXELS (160) #define TOPAZ_WIDTH_BYTES (TOPAZ_WIDTH_PIXELS / 8) #define TOPAZ_WIDTH_WORDS (TOPAZ_WIDTH_PIXELS / 16) void renderTopaz(void) { int plane; uint16_t bltcon0, bltcmod; uint8_t *bltbpt; bltcon0 = 0xca + (1 << 8) + (1 << 9) + (1 << 10) + (1 << 11); bltcmod = screenSetup.byteWidth - TOPAZ_WIDTH_BYTES; bltbpt = TopazBitplanes; for (plane = 0; plane < 3; ++plane) { custom.bltcon0 = bltcon0; custom.bltcon1 = 0; custom.bltafwm = 0xffff; custom.bltalwm = 0xffff; custom.bltapt = MaskBitplane; custom.bltbpt = bltbpt; custom.bltcpt = currentScreen.planes[plane] + 8; custom.bltdpt = currentScreen.planes[plane] + 8; custom.bltamod = 0; custom.bltbmod = 0; custom.bltcmod = bltcmod; custom.bltdmod = bltcmod; custom.bltsize = TOPAZ_WIDTH_WORDS + (256 << 6); bltbpt += TOPAZ_WIDTH_BYTES * 256; WaitBlit(); } } int main(void) { uint16_t *copperlist, *currentCopperlist, *currentCopperColors, result, *currentSpriteCopperlist; uint32_t spriteDataPointer; int i, x, y, height, plane; struct BunRenderer bunRenderer; printf("\nCool bun blitter, copper, and sprite demo by John Bintz\n"); printf("\n"); printf("This is my first real go at writing graphics code for the Amiga.\n"); printf("It's a combination of C (SAS/C) and Assembler (DevPac), with a Ruby\n"); printf("script to do some image processing. The screen only uses three\n"); printf("bitplanes -- one color is the background, two colors are the flying\n"); printf("cool bun logo white and black, and the remaining 5 colors are used\n"); printf("by the Topaz smiling art. The Ruby script will process the PNG file\n"); printf("and figure out the best 5 colors (plus b&w) for that line of the\n"); printf("image, setting the colors via copperlist for that line.\n"); printf("It also builds the clipping mask for the blitter.\n\n"); printf("And, I'm also using sprites to add more colors to the Topaz art.\n"); printf("The Ruby script will figure out what small areas of each line weren't\n"); printf("covered by the bitplane colors and use the 8 available sprites,\n"); printf("changing the colors on each line via copper, to fill in the gaps.\n"); printf("Cool buns are animated via blitter rather than sprites, but I\n"); printf("managed to get it to run at a decent speed regardless.\n"); printf("\nEnjoy, and thanks for watching!\n"); printf("John (theindustriousrabbit.com)\n\n"); setupScreen(&screenSetup, SCREEN_WIDTH, SCREEN_HEIGHT, 3); setupInitialCurrentScreen(&screenSetup, ¤tScreen); setupBunRenderer(&bunRenderer, &screenSetup, ¤tScreen); // blitter copy the first bitplane row down to the second copperlist = prepareNewCopperlist(); currentCopperlist = addDisplayToCopperlist( copperlist, &screenSetup, ¤tScreen, &copperlistBitplanePointers ); currentCopperColors = CopperColors; currentSpriteCopperlist = SpriteCopperlist; *(currentCopperlist++) = custom_color + 2; *(currentCopperlist++) = 0x000; *(currentCopperlist++) = custom_color + 4; *(currentCopperlist++) = 0xfff; for (i = 0; i < 8; ++i) { spriteDataPointer = (uint32_t)&SpriteData; spriteDataPointer += ((256 + 2) * 4) * i; *(currentCopperlist++) = custom_sprite + i * 4; *(currentCopperlist++) = (spriteDataPointer >> 16); *(currentCopperlist++) = custom_sprite + 2 + i * 4; *(currentCopperlist++) = (spriteDataPointer & 0xffff); } *(currentCopperlist++) = custom_color; *(currentCopperlist++) = 0x3a6; for (y = 0; y < 256; ++y) { for (i = 0; i < 8; ++i) { // set sprite color *(currentCopperlist++) = custom_color + 32 + ( // sprite color group (i / 2) * 4 + // 0 is transparent 1 + i % 2 ) * 2; *(currentCopperlist++) = *(currentSpriteCopperlist++); // set sprite position *(currentCopperlist++) = custom_sprite_control + i * 8; *(currentCopperlist++) = *(currentSpriteCopperlist++); *(currentCopperlist++) = custom_sprite_control + i * 8 + 2; *(currentCopperlist++) = *(currentSpriteCopperlist++); } for (i = 3; i < 8; ++i) { *(currentCopperlist++) = custom_color + (i * 2); *(currentCopperlist++) = *(currentCopperColors++); } *(currentCopperlist++) = 1 + ((31 + (256 / 4)) << 1) + ((44 + y) << 8); *(currentCopperlist++) = 0xFFFE; } endCopperlist(currentCopperlist); takeOverSystem(); setCopperlist(copperlist); setUpDisplay((uint32_t)screenSetup.bitplanes); i = 0; while (1) { swapCurrentScreenBuffer(&screenSetup, ¤tScreen); clearCurrentBuns(&bunRenderer); renderBunFrame(i, &bunRenderer); renderTopaz(); updateDisplayInCopperList( &screenSetup, ¤tScreen, copperlistBitplanePointers ); WaitBOF(250); if ((ciaa.ciapra >> 6) != 3) break; i++; i %= FRAMES_FOR_SCREEN; } giveBackSystem(); teardownScreen(&screenSetup); freeCopperlist(copperlist); teardownBunRenderer(); return 0; }