/** * Chunky vertical copperbars demo * Copyright 2023 John Bintz * Licensed under the MIT License * https://theindustriousrabbit.com */ #include #include #include #include #include #include #include #include #include #include extern struct GfxBase *GfxBase; extern struct Custom far custom; extern struct CIA far ciaa, ciab; // this is faster than // custom.vhposr + (custom.vposr << 16) static volatile ULONG *custom_vposr = (volatile ULONG *)0xdff004; #define offsetof(s, m) &((struct s *)0)->m #define BITPLANE_SIZE (320/8)*256 #define BPLCON0_COLOR (0x200) #define BPLCON0_BPU_1 (0x1000) static UWORD colors[] = {0xf00,0x0f0,0xff0,0x0ff}; int main(void) { struct View *OldView = ((struct GfxBase *)GfxBase)->ActiView; ULONG OldCopper = (ULONG)((struct GfxBase *)GfxBase)->copinit; ULONG OldDMACON, OldINTENA, OldINTREQ, OldADKCON; int currentY, colorBar, xPos; void *copperlist; UWORD *copperlist_ptr; APTR *bitplane; // how much can we avoid hard coding into our code? UWORD custom_bplpt = (UWORD)offsetof(Custom, bplpt); UWORD custom_color = (UWORD)offsetof(Custom, color); LoadView(NULL); WaitTOF(); WaitTOF(); OwnBlitter(); WaitBlit(); Forbid(); OldDMACON = custom.dmaconr | 0x8000; OldINTENA = custom.intenar | 0x8000; OldINTREQ = custom.intreqr | 0x8000; OldADKCON = custom.adkconr | 0x8000; // disable interrupts custom.intena = 0xc000; custom.intena = 0x3fff; // set up dma custom.dmacon = DMAF_SETCLR | DMAF_COPPER | DMAF_RASTER; custom.dmacon = DMAF_AUDIO | DMAF_DISK | DMAF_SPRITE | DMAF_BLITTER; // 4 bars = WAIT + MOVE (8 bytes) 8 times * 312 + ~100 for setup = 21000 should do it copperlist = AllocMem(21000, MEMF_CHIP | MEMF_CLEAR); bitplane = (APTR *)AllocMem(BITPLANE_SIZE, MEMF_PUBLIC|MEMF_CHIP|MEMF_CLEAR); // default copperlist has just STOP ((ULONG *)copperlist)[0] = 0xfffffffe; // set up 1 bitplane pal display custom.bplcon0 = BPLCON0_COLOR | BPLCON0_BPU_1; custom.bplcon1 = 0; custom.bpl1mod = 0; custom.diwstrt = 0x2c21; custom.diwstop = 0x2cc1; custom.ddfstrt = 0x0038; custom.ddfstop = 0x00d0; // substitute our minimal copperlist now custom.cop1lc = (ULONG)copperlist; // neither HID button 0 is down while ((ciaa.ciapra >> 6) == 3) { // rebuild copperlist copperlist_ptr = (UWORD *)copperlist; // bpl1pth *(copperlist_ptr++) = custom_bplpt; *(copperlist_ptr++) = ((ULONG)bitplane >> 16) & 0xffff; // bpl1ptl *(copperlist_ptr++) = custom_bplpt + 2; *(copperlist_ptr++) = (ULONG)bitplane & 0xffff; *(copperlist_ptr++) = custom_color; *(copperlist_ptr++) = 0x0f00; for (currentY = 0; currentY < 312; currentY++) { for (colorBar = 0; colorBar < 4; colorBar++) { xPos = 0x68 + (colorBar * 24); *(copperlist_ptr++) = ((currentY & 0xff) << 8) | xPos | 0x1; *(copperlist_ptr++) = 0xfffe; *(copperlist_ptr++) = custom_color; *(copperlist_ptr++) = colors[colorBar]; *(copperlist_ptr++) = ((currentY & 0xff) << 8) | xPos + 2 | 0x1; *(copperlist_ptr++) = 0xfffe; *(copperlist_ptr++) = custom_color; *(copperlist_ptr++) = 0x000; } // PAL workaround if (currentY == 255) { *(copperlist_ptr++) = 0xffdf; *(copperlist_ptr++) = 0xfffe; } } // end the copperlist *(copperlist_ptr++) = 0xffff; *(copperlist_ptr++) = 0xfffe; // vbl wait // this will not work on NTSC! while ((*custom_vposr & 0x1FF00) != (300 << 8)) {} } FreeMem(bitplane, BITPLANE_SIZE); FreeMem(copperlist, 21000); custom.dmacon = 0x7FFF; custom.dmacon = OldDMACON; custom.intena = 0x7FFF; custom.intena = OldINTENA; custom.intreq = 0x7FFF; custom.intreq = OldINTREQ; custom.adkcon = 0x7FFF; custom.adkcon = OldADKCON; custom.cop1lc = OldCopper; LoadView(OldView); WaitTOF(); WaitTOF(); WaitBlit(); DisownBlitter(); Permit(); }