diff --git a/bun.c b/bun.c new file mode 100644 index 0000000..d000357 --- /dev/null +++ b/bun.c @@ -0,0 +1,166 @@ +#include "screen.h" +#include "bun.h" + +extern unsigned char far coolbun[]; + +unsigned char *coolbunArea; + +#define COOL_BUN_WIDTH (32) +#define COOL_BUN_WIDTH_BYTES (COOL_BUN_WIDTH / 8) +#define COOL_BUN_HEIGHT (32) +#define COOL_BUN_PLANES (2) + +#define COOL_BUN_PLANE_SIZE (COOL_BUN_WIDTH_BYTES * COOL_BUN_HEIGHT) +#define COOL_BUN_MEMORY_SIZE (COOL_BUN_PLANE_SIZE * COOL_BUN_PLANES) + +void setupBun() { + unsigned char *currentCoolBunArea, *currentCoolBun; + + coolbunArea = AllocMem(COOL_BUN_MEMORY_SIZE, MEMF_CHIP | MEMF_CLEAR); + currentCoolBun = coolbun; + + currentCoolBunArea = coolbunArea; + + for (plane = 0; plane < COOL_BUN_PLANES; ++plane) { + for (y = 0; y < COOL_BUN_HEIGHT; ++y) { + for (x = 0; x < COOL_BUN_WIDTH_BYTES; ++x) { + *(currentCoolBunArea++) = *(currentCoolBun++); + } + } + } +} + +void teardownBun() { + FreeMem(coolbunArea, COOL_BUN_MEMORY_SIZE); +} + +void bun_offRightSide(int plusXValue, int y, struct ScreenSetup *screenSetup) { + uint8_t i, plane = 0; + uint8_t shift = plusXValue & 15; + uint8_t wordShift = (plusXValue >> 4); + uint16_t bltalwm; + + for (plane = 0; plane < 2; ++plane) { + custom.bltcon0 = 0xc0 + (1 << 8) + (1 << 10) + (shift << 12); + custom.bltcon1 = (shift << 12); + + custom.bltadat = 0xffff; + custom.bltbpt = coolbunArea + plane * COOL_BUN_PLANE_SIZE; + custom.bltdpt = screenSetup->memoryStart + + plane * screenSetup->nextBitplaneAdvance + + (y * screenSetup.width + screenSetup.width - COOL_BUN_WIDTH) / 8 + + wordShift * 2; + + custom.bltafwm = 0xffff; + bltalwm = 0x0000; + for (i = 0; i < 15 - shift; ++i) { + bltalwm += (1 << (15 - i)); + } + custom.bltalwm = bltalwm; + + custom.bltbmod = wordShift * 2; + custom.bltdmod = (screenSetup.width - COOL_BUN_WIDTH) / 8 + wordShift * 2; + + custom.bltsize = 2 - wordShift + (COOL_BUN_HEIGHT << 6); + + WaitBlit(); + } +} + +#define BLTCON0( \ + minterm, aChan, bChan, cChan, dChan, shift \ +) (minterm + (aChan << 11) + (bChan << 10) + (cChan << 9) + (dChan << 8) + (shift << 12) +#define BLTCON1(descending, shift) ((descending << 1) + (shift << 12)) + +void bun_offLeftSide(int minusXValue, int y, struct CurrentScreen *currentScreen) { + unsigned char plane; + uint8_t shift = minusXValue & 15; + uint8_t wordShift = (minusXValue >> 4); + uint8_t i; + uint16_t bltalwm; + + // y can't be 0 otherwise we will corrupt memory for now + if (y == 0) return; + + for (plane = 0; plane < 2; ++plane) { + // shift left, so descending + custom.bltcon0 = BLTCON0(0xc0, 0, 1, 0, 1, shift); + custom.bltcon1 = BLTCON1(1, shift); + + // a has a mask we're shifting + custom.bltadat = 0xffff; + // b has bun data + custom.bltbpt = coolbunArea + 2 + ((COOL_BUN_HEIGHT - 1) * 4) + plane * COOL_BUN_PLANE_SIZE; + + // d is the part on screen + custom.bltdpt = screenSetup.memoryStart + screenSetup.nextBitplaneAdvance * plane + (screenSetup.width * (y + COOL_BUN_HEIGHT - 1) / 8) + 2 - wordShift * 2; + + custom.bltafwm = 0xffff; + bltalwm = 0x0000; + for (i = 0; i < 15 - shift; ++i) { + bltalwm += (1 << i); + } + custom.bltalwm = bltalwm; + + custom.bltbmod = wordShift * 2; + custom.bltdmod = screenSetup.width / 8 - 4 + wordShift * 2; + + custom.bltsize = 2 - wordShift + (COOL_BUN_HEIGHT << 6); + + WaitBlit(); + } +} + +void bun_anywhere(int x, int y, struct ScreenSetup *screenSetup) { + uint8_t plane; + uint8_t shift = x & 15; + uint8_t needsExtraWord = shift != 0; + + for (plane = 0; plane < 2; ++plane) { + // if we extend the bun area by a word, we only need one write + + // buns will never interfere with a background so they don't need a mask + // they do need the scratch area though + custom.bltcon0 = 0xc0 + (1 << 8) + (1 << 10) + (shift << 12); + custom.bltcon1 = (shift << 12); + + custom.bltadat = 0xffff; + custom.bltbpt = coolbunArea + plane * COOL_BUN_PLANE_SIZE; + custom.bltdpt = screenSetup.memoryStart + WORD_ALIGNED_BYTE_POSITION(screenSetup.width, x, y) + screenSetup.nextBitplaneAdvance * plane; + + // custom.bltdpt = screenSetup.memoryStart; + custom.bltafwm = 0xffff; + if (needsExtraWord) { + custom.bltalwm = 0x0000; + } else { + custom.bltalwm = 0xffff; + } + custom.bltbmod = -(needsExtraWord * 2); + custom.bltdmod = (screenSetup.width / 8) - COOL_BUN_WIDTH_BYTES - (needsExtraWord * 2); + custom.bltsize = (2 + needsExtraWord) + (COOL_BUN_HEIGHT << 6); + + WaitBlit(); + } +} + +void renderBun(int x, int y, struct CurrentScreen *currentScreen) { + /** + * Conditions that will cause the program to crash if met. If your bun + * isn't rendering, it's due to here. + * + * TODO: Handle top/bottom off-screen as well. + */ + if (x < -31) return; + if (x > currentScreen->pixelWidth + 31) return; + if (y < 1) return; + if (y > currentScreen->pixelHeight- COOL_BUN_HEIGHT - 1) return; + + if (x < 0) { + bun_offLeftSide(-x, y, currentScreen); + } else if (x > screenSetup.width - COOL_BUN_WIDTH) { + bun_offRightSide(x - (currentScreen->pixelWidth - COOL_BUN_WIDTH), y, currentScreen); + } else { + bun_anywhere(x, y, currentScreen); + } +} + diff --git a/bun.h b/bun.h new file mode 100644 index 0000000..9cdc378 --- /dev/null +++ b/bun.h @@ -0,0 +1,10 @@ +#ifndef __BUN_H__ +#define __BUN_H__ + +#include "screen.h" + +void setupBun(); +void renderBun(int x, int y, struct ScreenSetup *screenSetup); +void teardownBun(); + +#endif diff --git a/main b/main index a245d7e..3aeb5e4 100755 Binary files a/main and b/main differ diff --git a/main.c b/main.c index 7fdeefd..9d01e32 100644 --- a/main.c +++ b/main.c @@ -15,17 +15,9 @@ #include "screen.h" #include "types.h" +#include "bun.h" extern struct Custom far custom; -extern unsigned char far coolbun[]; - -#define COOL_BUN_WIDTH (32) -#define COOL_BUN_WIDTH_BYTES (COOL_BUN_WIDTH / 8) -#define COOL_BUN_HEIGHT (32) -#define COOL_BUN_PLANES (2) - -#define COOL_BUN_PLANE_SIZE (COOL_BUN_WIDTH_BYTES * COOL_BUN_HEIGHT) -#define COOL_BUN_MEMORY_SIZE (COOL_BUN_PLANE_SIZE * COOL_BUN_PLANES) // this should be large enough to hold one bitplane of the largest object // you are blitting, plus one additional word on each side @@ -35,160 +27,30 @@ extern unsigned char far coolbun[]; volatile short *dbg = (volatile short *)0x100; -unsigned char *coolbunArea; unsigned char *scratchArea; struct ScreenSetup screenSetup; +struct CurrentScreen currentScreen; -void bun_offRightSide(int plusXValue, int y) { - uint8_t i, plane = 0; - uint8_t shift = plusXValue & 15; - uint8_t wordShift = (plusXValue >> 4); - uint16_t bltalwm; - - for (plane = 0; plane < 2; ++plane) { - custom.bltcon0 = 0xc0 + (1 << 8) + (1 << 10) + (shift << 12); - custom.bltcon1 = (shift << 12); - - custom.bltadat = 0xffff; - custom.bltbpt = coolbunArea + plane * COOL_BUN_PLANE_SIZE; - custom.bltdpt = screenSetup.memoryStart + plane * screenSetup.nextBitplaneAdvance + (y * screenSetup.width + screenSetup.width - COOL_BUN_WIDTH) / 8 + wordShift * 2; - - custom.bltafwm = 0xffff; - bltalwm = 0x0000; - for (i = 0; i < 15 - shift; ++i) { - bltalwm += (1 << (15 - i)); - } - custom.bltalwm = bltalwm; - - custom.bltbmod = wordShift * 2; - custom.bltdmod = (screenSetup.width - COOL_BUN_WIDTH) / 8 + wordShift * 2; - - custom.bltsize = 2 - wordShift + (COOL_BUN_HEIGHT << 6); - - WaitBlit(); - } -} - -void bun_offLeftSide(int minusXValue, int y) { - unsigned char plane; - uint8_t shift = minusXValue & 15; - uint8_t wordShift = (minusXValue >> 4); - uint8_t i; - uint16_t bltalwm; - - // y can't be 0 otherwise we will corrupt memory for now - if (y == 0) return; - - for (plane = 0; plane < 2; ++plane) { - // shift left, so desccending - custom.bltcon0 = 0xc0 + (1 << 8) + (1 << 10) + (shift << 12); - custom.bltcon1 = (1 << 1) + (shift << 12); - - // a has a mask we're shifting - custom.bltadat = 0xffff; - // b has bun data - custom.bltbpt = coolbunArea + 2 + ((COOL_BUN_HEIGHT - 1) * 4) + plane * COOL_BUN_PLANE_SIZE; - - // d is the part on screen - custom.bltdpt = screenSetup.memoryStart + screenSetup.nextBitplaneAdvance * plane + (screenSetup.width * (y + COOL_BUN_HEIGHT - 1) / 8) + 2 - wordShift * 2; - - custom.bltafwm = 0xffff; - bltalwm = 0x0000; - for (i = 0; i < 15 - shift; ++i) { - bltalwm += (1 << i); - } - custom.bltalwm = bltalwm; - - custom.bltbmod = wordShift * 2; - custom.bltdmod = screenSetup.width / 8 - 4 + wordShift * 2; - - custom.bltsize = 2 - wordShift + (COOL_BUN_HEIGHT << 6); - - WaitBlit(); - } -} - -void bun_anywhere(int x, int y) { - uint8_t plane; - uint8_t shift = x & 15; - uint8_t needsExtraWord = shift != 0; - - for (plane = 0; plane < 2; ++plane) { - // if we extend the bun area by a word, we only need one write - - // buns will never interfere with a background so they don't need a mask - // they do need the scratch area though - custom.bltcon0 = 0xc0 + (1 << 8) + (1 << 10) + (shift << 12); - custom.bltcon1 = (shift << 12); - - custom.bltadat = 0xffff; - custom.bltbpt = coolbunArea + plane * COOL_BUN_PLANE_SIZE; - custom.bltdpt = screenSetup.memoryStart + WORD_ALIGNED_BYTE_POSITION(screenSetup.width, x, y) + screenSetup.nextBitplaneAdvance * plane; - - // custom.bltdpt = screenSetup.memoryStart; - custom.bltafwm = 0xffff; - if (needsExtraWord) { - custom.bltalwm = 0x0000; - } else { - custom.bltalwm = 0xffff; - } - custom.bltbmod = -(needsExtraWord * 2); - custom.bltdmod = (screenSetup.width / 8) - COOL_BUN_WIDTH_BYTES - (needsExtraWord * 2); - custom.bltsize = (2 + needsExtraWord) + (COOL_BUN_HEIGHT << 6); - - WaitBlit(); - } -} - -void renderBun(int x, int y) { - if (x < -31) return; - if (x > screenSetup.width + 31) return; - if (y < 1) return; - if (y > screenSetup.height - COOL_BUN_HEIGHT - 1) return; - - if (x < 0) { - bun_offLeftSide(-x, y); - } else if (x > screenSetup.width - COOL_BUN_WIDTH) { - bun_offRightSide(x - (screenSetup.width - COOL_BUN_WIDTH), y); - } else { - bun_anywhere(x, y); - } -} +#define offsetof(s, m) &((struct s *)0)->m +uint16_t custom_color = (uint16_t)offsetof(Custom, color); int main(void) { uint16_t *copperlist, *currentCopperlist; int i, x, y, plane, result; int blitShiftRight, memoryXOffset, blitWidth; - int bunPosition = -31; - - color_t colors[16]; - - unsigned char *currentCoolBunArea, *currentCoolBun; - - coolbunArea = AllocMem(COOL_BUN_MEMORY_SIZE, MEMF_CHIP | MEMF_CLEAR); - currentCoolBun = coolbun; - - scratchArea = AllocMem(SCRATCH_AREA_MEMORY_SIZE, MEMF_CHIP | MEMF_CLEAR); + color_t colors[8]; colors[0] = 0x09b8; colors[1] = 0x0000; colors[2] = 0x0fff; colors[3] = 0x000f; - prepareScreen(&screenSetup, SCREEN_WIDTH, SCREEN_HEIGHT, 4); - allocateScreenMemory(&screenSetup); - - currentCoolBunArea = coolbunArea; - - for (plane = 0; plane < COOL_BUN_PLANES; ++plane) { - for (y = 0; y < COOL_BUN_HEIGHT; ++y) { - for (x = 0; x < COOL_BUN_WIDTH_BYTES; ++x) { - *(currentCoolBunArea++) = *(currentCoolBun++); - } - } - } + setupScreen(&screenSetup, SCREEN_WIDTH, SCREEN_HEIGHT, 3); + setupInitialCurrentScreen(&screenSetup, ¤tScreen); + teardownScreen(&screenSetup); + return 0; // blitter copy the first bitplane row down to the second @@ -200,11 +62,38 @@ int main(void) { setUpDisplay(&screenSetup); currentCopperlist = addDisplayToCopperlist(copperlist, &screenSetup); - currentCopperlist = addColorsToCopperlist(currentCopperlist, colors, 16); + //currentCopperlist = addColorsToCopperlist(currentCopperlist, colors, 16); + *(currentCopperlist++) = custom_color; + *(currentCopperlist++) = 0x000; + + *(currentCopperlist++) = custom_color + 2; + *(currentCopperlist++) = 0x000; + + *(currentCopperlist++) = custom_color + 4; + *(currentCopperlist++) = 0xfff; + + *(currentCopperlist++) = custom_color + 6; + *(currentCopperlist++) = 0x00F; + + for (y = 0; y < 256; ++y) { + *(currentCopperlist++) = 1 + (31 << 1) + ((44 + y) << 8); + *(currentCopperlist++) = 0xFFFE; + *(currentCopperlist++) = custom_color; + *(currentCopperlist++) = 0x9b8; + + *(currentCopperlist++) = 1 + (31 + (320 / 4) << 1) + ((44 + y) << 8); + *(currentCopperlist++) = 0xFFFE; + *(currentCopperlist++) = custom_color; + *(currentCopperlist++) = 0x000; + } + endCopperlist(currentCopperlist); for (i = -31; i < screenSetup.width - 1; ++i) { - y = WaitBOF(250); + //y = WaitBOF(250); + WaitTOF(); + + /* for (plane = 0; plane < 2; ++plane) { custom.bltcon0 = 0xc0 + (1 << 8); custom.bltcon1 = 0; @@ -216,18 +105,22 @@ int main(void) { custom.bltsize = 20 + (COOL_BUN_MEMORY_SIZE << 6); WaitBlit(); } + */ - renderBun(i, 45); + renderBun(i, 45, &screenSetup); + } + + for (i = 0; i < 100; ++i) { + WaitTOF(); } giveBackSystem(); - freeScreenMemory(&screenSetup); + freeScreen(&screenSetup); freeCopperlist(copperlist); - FreeMem(coolbunArea, COOL_BUN_MEMORY_SIZE); - FreeMem(scratchArea, SCRATCH_AREA_MEMORY_SIZE); + teardownBun(); return 0; } diff --git a/screen.c b/screen.c index c17fa07..379aa98 100644 --- a/screen.c +++ b/screen.c @@ -4,31 +4,69 @@ #include #include -void allocateScreenMemory(struct ScreenSetup *screenSetup) { - char *memory = (char *)AllocMem( +/** + * Includes double buffer space + */ +#define TOTAL_SCREEN_SETUP_SIZE(s) ((s->width / 8) * s->height * s->bitplanes * 2) + +void setupScreen( + struct ScreenSetup *screenSetup, + uint16_t width, + uint16_t height, + uint8_t bitplanes +) { + unsigned char *memory; + + screenSetup->width = width; + screenSetup->height = height; + screenSetup->bitplanes = bitplanes; + + memory = (unsigned char *)AllocMem( TOTAL_SCREEN_SETUP_SIZE(screenSetup), MEMF_CLEAR | MEMF_CHIP ); screenSetup->memoryStart = memory; + screenSetup->byteWidth = width / 8; + + // memory is not interleaved + screenSetup->nextBitplaneAdvance = screenSetup->byteWidth * height; + screenSetup->nextBufferAdvance = screenSetup->nextBitplaneAdvance * bitplanes; } -void freeScreenMemory(struct ScreenSetup *screenSetup) { +void teardownScreen( + struct ScreenSetup *screenSetup +) { FreeMem( screenSetup->memoryStart, TOTAL_SCREEN_SETUP_SIZE(screenSetup) ); } -void prepareScreen( +void setCurrentScreen( struct ScreenSetup *screenSetup, - uint16_t width, - uint16_t height, - uint8_t bitplanes + struct CurrentScreen *currentScreen, + short int buffer ) { - screenSetup->width = width; - screenSetup->height = height; - screenSetup->bitplanes = bitplanes; - screenSetup->nextBitplaneAdvance = width * height / 8; - screenSetup->currentBuffer = 0; + int plane; + + currentScreen->currentBuffer = buffer; + + for (plane = 0; plane < screenSetup->bitplanes; ++plane) { + currentScreen->planes[plane] = screenSetup->memoryStart + + buffer * screenSetup->nextBufferAdvance + + plane * screenSetup->nextBitplaneAdvance; + } } + +void setupInitialCurrentScreen( + struct ScreenSetup *screenSetup, + struct CurrentScreen *currentScreen +) { + currentScreen->pixelWidth = screenSetup->width; + currentScreen->pixelHeight = screenSetup->height; + currentScreen->byteWidth = screenSetup->byteWidth; + + setCurrentScreen(screenSetup, currentScreen, 0); +} + diff --git a/screen.h b/screen.h index 728d6b9..c7e878d 100644 --- a/screen.h +++ b/screen.h @@ -3,28 +3,41 @@ #include "types.h" -struct ScreenSetup { - short int width; - short int height; - short int bitplanes; - unsigned char *memoryStart; - short int nextBitplaneAdvance; - - short int currentBuffer; -}; - #define SCREEN_WIDTH (320) #define SCREEN_HEIGHT (256) -#define TOTAL_SCREEN_SETUP_SIZE(s) ((s->width / 8) * s->height * s->bitplanes * 2) +struct ScreenSetup { + // human entered + uint16_t width; + uint16_t height; + short int bitplanes; -void allocateScreenMemory(struct ScreenSetup *screenSetup); -void freeScreenMemory(struct ScreenSetup *screenSetup); -void prepareScreen( + // calculated + unsigned char *memoryStart; + uint16_t byteWidth; + uint16_t nextBitplaneAdvance; + uint16_t nextBufferAdvance; +}; + +struct CurrentScreen { + uint16_t currentBuffer; + uint16_t pixelWidth; + uint16_t byteWidth; + uint16_t pixelHeight; + unsigned char *planes[8]; +}; + +void setupScreen( struct ScreenSetup *screenSetup, uint16_t width, uint16_t height, uint8_t bitplanes ); +void teardownScreen(struct ScreenSetup *screenSetup); +void setCurrentScreen( + struct ScreenSetup *screenSetup, + struct CurrentScreen *currentScreen, + short int buffer +); #endif diff --git a/smakefile b/smakefile index cb94cdf..2d770f7 100644 --- a/smakefile +++ b/smakefile @@ -1,3 +1,5 @@ +MAIN_OBJS = main.o images.o system.lib screen.o bun.o + all: main .c.o: @@ -9,8 +11,8 @@ all: main system.lib: system/system.o system/copper.o system/blitter.o sc objectlibrary=system.lib system/system.o system/copper.o system/blitter.o -main: main.o images.o system.lib screen.o - sc link to main main.o system.lib screen.o images.o +main: $(MAIN_OBJS) + sc link to main $(MAIN_OBJS) test: blitter_test.o blitter.o system.o sc link to blitter_test identifierlength=32 math=standard blitter_test.o blitter.o cutest/CuTest.c system.o