From 910a735c08a14ff6f5f7360051e422025785f1a3 Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Tue, 8 Oct 2019 19:58:26 -0500 Subject: [PATCH] New blitting routines working! --- joeylib/src/jIIgs.asm | 179 +++++++++++++++++++++--------------------- joeylib/src/jPC.c | 32 ++++---- joeylib/src/joey.h | 10 +-- joeylib/src/test.c | 85 +++++++++++++++----- 4 files changed, 179 insertions(+), 127 deletions(-) diff --git a/joeylib/src/jIIgs.asm b/joeylib/src/jIIgs.asm index d296d1f..3632465 100644 --- a/joeylib/src/jIIgs.asm +++ b/joeylib/src/jIIgs.asm @@ -35,71 +35,67 @@ VblTime ds 2 ; Integer Counter ;---------------------------------------- -; Blit an 8x8 block. ***TODO*** Unroll loops +; Blit an 8x8 block to (almost) anywhere on a surface. ;---------------------------------------- asmB88 start -so equ 1 ; Source Pixels Offset -to equ 3 ; Target Pixels Offset +source equ 1 ; Source Pixels Offset +target equ 3 ; Target Pixels Offset t equ 5 ; Temp xc equ 7 ; X Counter yc equ 9 ; Y Counter - jsubroutine (4:surface,4:tiles,2:cx1,2:cy1,2:cx2,2:cy2),10 + jsubroutine (4:surface,4:tiles,2:sx,2:sy,2:tx,2:ty),10 using GlobalData ; Find offset into tile memory - lda cx1 ; Multiply cx1 by 4 to get offset (two pixels per byte) + lda sx ; Multiply sx by 4 to get offset (two pixels per byte) asl a asl a sta t clc - lda cy1 ; Multiply cy1 by 16 to get index into scanline table + lda sy ; Multiply sy by 16 to get index into scanline table asl a asl a asl a asl a ; y screen location is now in the accumulator - tax + tay clc - lda >ScanTable,x ; Load byte offset of y position from table + lda ScanTable,y ; Load byte offset of y position from table adc t ; Add t to scanline offset - sta so ; Offset to start of source pixels + sta source ; Offset to start of source pixels + +; Divide target horizontal position by two since there are two pixels per byte + lda tx ; Load X target position into accumulator + lsr a ; Shift Right - divide by 2 + clc + sta tx ; Store it back into cx2 ; Find offset into target surface memory - clc - lda cx2 ; Multiply cx2 by 4 to get offset (two pixels per byte) - asl a - asl a - sta t - clc - lda cy2 ; Multiply cy2 by 16 to get index into scanline table - asl a - asl a - asl a - asl a ; y screen location is now in the accumulator - clc - tax - lda >ScanTable,x ; Load byte offset of y position from table - adc t ; Add t to scanline offset - sta to ; Offset to start of target pixels + lda ty ; Load ty to get index into scanline table + asl a ; Multiply by two to get offset into scanline table (two bytes per entry in table) + tay + lda ScanTable,y ; Load byte offset of y position from table + adc tx ; Add x position to scanline offset + sta target ; Offset to start of target pixels lda #0 ; Load 0 into X and Y counters sta xc sta yc -blitTop ldy so ; Load Y register with source pixel offset +blitTop ldy source ; Load Y register with source pixel offset lda [tiles],y ; Load 4 tile pixels - ldy to ; Load Y register with target pixel offset + ldy target ; Load Y register with target pixel offset sta [surface],y ; Store 4 pixels into screen clc ; Increment to next pixel target quad lda #2 - adc to - sta to + adc target + sta target clc ; Increment to next pixel source quad lda #2 - adc so - sta so + adc source + sta source clc lda xc ; Increment X counter @@ -112,12 +108,12 @@ blitTop ldy so ; Load Y register with source pixel offset sta xc clc ; Increment target offset lda #156 - adc to - sta to + adc target + sta target clc ; Increment source offset lda #156 - adc so - sta so + adc source + sta source clc lda yc ; Increment Y counter adc #1 @@ -130,88 +126,84 @@ blitTop ldy so ; Load Y register with source pixel offset ;---------------------------------------- -; Blit an 8x8 block with alpha. +; Blit an 8x8 block with alpha to (almost) anywhere on a surface. ;---------------------------------------- asmB88a start -so equ 1 ; Source Pixels Offset -to equ 3 ; Target Pixels Offset -mo equ 5 ; Mask Offset +source equ 1 ; Source Pixels Offset +target equ 3 ; Target Pixels Offset +mask equ 5 ; Mask Offset t equ 7 ; Temp xc equ 9 ; X Counter yc equ 11 ; Y Counter - jsubroutine (4:surface,4:tiles,2:cx1,2:cy1,2:cx2,2:cy2,2:offset),12 + jsubroutine (4:surface,4:tiles,2:sx,2:sy,2:tx,2:ty,2:offset),12 using GlobalData ; Find offset into tile memory - lda cx1 ; Multiply cx1 by 4 to get offset (two pixels per byte) + lda sx ; Multiply sx by 4 to get offset (two pixels per byte) asl a asl a sta t clc - lda cy1 ; Multiply cy1 by 16 to get index into scanline table + lda sy ; Multiply sy by 16 to get index into scanline table asl a asl a asl a asl a ; y screen location is now in the accumulator - tax + tay clc - lda >ScanTable,x ; Load byte offset of y position from table + lda ScanTable,y ; Load byte offset of y position from table adc t ; Add t to scanline offset - sta so ; Offset to start of source pixels + sta source ; Offset to start of source pixels ; Find offset into tile memory for mask data lda offset ; Load offset asl a ; Multiply by 4 asl a clc - adc so ; Add to source pixel offset - sta mo ; Offset to start of mask pixels + adc source ; Add to source pixel offset + sta mask ; Offset to start of mask pixels + +; Divide target horizontal position by two since there are two pixels per byte + lda tx ; Load X target position into accumulator + lsr a ; Shift Right - divide by 2 + clc + sta tx ; Store it back into tx ; Find offset into target surface memory - clc - lda cx2 ; Multiply cx2 by 4 to get offset (two pixels per byte) - asl a - asl a - sta t - clc - lda cy2 ; Multiply cy2 by 16 to get index into scanline table - asl a - asl a - asl a - asl a ; y screen location is now in the accumulator - clc - tax - lda >ScanTable,x ; Load byte offset of y position from table - adc t ; Add t to scanline offset - sta to ; Offset to start of target pixels + lda ty ; Load ty to get index into scanline table + asl a ; Multiply by two to get offset into scanline table (two bytes per entry in table) + tay + lda ScanTable,y ; Load byte offset of y position from table + adc tx ; Add x position to scanline offset + sta target ; Offset to start of target pixels lda #0 ; Load 0 into X and Y counters sta xc sta yc -blitTop ldy to ; Load Y register with target pixel offset +blitTop ldy target ; Load Y register with target pixel offset lda [surface],y ; Load target pixels - ldy mo ; Load Y register with mask pixel offset + ldy mask ; Load Y register with mask pixel offset and [tiles],y ; AND with mask - ldy so ; Load Y register with source pixel offset + ldy source ; Load Y register with source pixel offset ora [tiles],y ; OR with source pixels - ldy to ; Load Y register with target pixel offset + ldy target ; Load Y register with target pixel offset sta [surface],y ; Store 4 pixels into screen clc ; Increment to next pixel target quad lda #2 - adc to - sta to + adc target + sta target clc ; Increment to next pixel source quad lda #2 - adc so - sta so + adc source + sta source clc ; Increment to next pixel mask quad lda #2 - adc mo - sta mo + adc mask + sta mask clc lda xc ; Increment X counter @@ -224,16 +216,16 @@ blitTop ldy to ; Load Y register with target pixel offset sta xc clc ; Increment target offset lda #156 - adc to - sta to + adc target + sta target clc ; Increment source offset lda #156 - adc so - sta so + adc source + sta source clc ; Increment mask offset lda #156 - adc mo - sta mo + adc mask + sta mask clc lda yc ; Increment Y counter adc #1 @@ -245,7 +237,6 @@ blitTop ldy to ; Load Y register with target pixel offset end - ;---------------------------------------- ; Set Border Color ;---------------------------------------- @@ -278,15 +269,21 @@ loopY equ 9 sta offset clc ; Find loop ending values - lda startX - adc width - sta loopX + lda width ; Load width of map to draw, in tiles + asl a ; Multiply by 8 to get pixels + asl a + asl a + adc startX ; Add starting position in pixels + sta loopX ; Store it clc - lda startY - adc height - sta loopY + lda height ; Load height of map to draw, in tiles + asl a ; Multiply by 8 to get pixels + asl a + asl a + adc startY ; Add starting position in pixels + sta loopY ; Store it - ldx startX ; Loop counters + ldx startX ; Initialize loop counters ldy startY drawTop phy ; Keep Y for later @@ -316,7 +313,9 @@ drawTop phy ; Keep Y for later ply ; Unclobber plx - inx ; Increment x loop + txa ; Increment x loop + adc #8 ; Increment in pixels + tax cpx loopX ; Loop until 'width' bcc drawTop @@ -325,7 +324,9 @@ drawTop phy ; Keep Y for later lda offset ; Add stride to offset adc stride sta offset - iny ; Increment y loop + tya ; Increment y loop + adc #8 ; Increment in pixels + tay cpy loopY ; Loop until 'height' bcc drawTop diff --git a/joeylib/src/jPC.c b/joeylib/src/jPC.c index 5266e5e..49b60c6 100644 --- a/joeylib/src/jPC.c +++ b/joeylib/src/jPC.c @@ -154,7 +154,7 @@ void jlDisplayPresent(void) { } -void jlDrawBlit8x8(jlSurfaceT source, jint16 cx1, jint16 cy1, jint16 cx2, jint16 cy2) { +void jlDrawBlit8x8(jlSurfaceT source, jint16 sx, jint16 sy, jint16 tx, jint16 ty) { int o1; int o2; int x; @@ -163,8 +163,9 @@ void jlDrawBlit8x8(jlSurfaceT source, jint16 cx1, jint16 cy1, jint16 cx2, jint16 jlPixelPairT *target = (jlPixelPairT *)_jlDrawTargetActual; // We mask off unused bits in the source tile location so they can be used to hold other data. - o1 = ((cy1 & 0x1f) * 8 * 160) + ((cx1 & 0x3f) * 4); - o2 = (cy2 * 8 * 160) + (cx2 * 4); + o1 = ((sy & 0x1f) * 8 * 160) + ((sx & 0x3f) * 4); // This is in tiles + o2 = ty * 160 + (int)(tx * 0.5); // This is in pixels... + if (jlUtilIsOdd(o2)) o2--; //...and must be even for (y=0; y<8; y++) { for (x=0; x<4; x++) { @@ -176,7 +177,7 @@ void jlDrawBlit8x8(jlSurfaceT source, jint16 cx1, jint16 cy1, jint16 cx2, jint16 } -void jlDrawBlit8x8a(jlSurfaceT source, jint16 cx1, jint16 cy1, jint16 cx2, jint16 cy2, byte offset) { +void jlDrawBlit8x8a(jlSurfaceT source, jint16 sx, jint16 sy, jint16 tx, jint16 ty, byte offset) { int mo; // Mask offset int so; // Source Pixel Offset int to; // Target Pixel Offset @@ -189,9 +190,10 @@ void jlDrawBlit8x8a(jlSurfaceT source, jint16 cx1, jint16 cy1, jint16 cx2, jint1 jlPixelPairT *target = (jlPixelPairT *)_jlDrawTargetActual; // We mask off unused bits in the source tile location so they can be used to hold other data. - mo = ((cy1 & 0x1f) * 8 * 160) + (((cx1 & 0x3f) + offset) * 4); - so = ((cy1 & 0x1f) * 8 * 160) + ((cx1 & 0x3f) * 4); - to = (cy2 * 8 * 160) + (cx2 * 4); + mo = ((sy & 0x1f) * 8 * 160) + (((sx & 0x3f) + offset) * 4); // This is in tiles + so = ((sy & 0x1f) * 8 * 160) + ((sx & 0x3f) * 4); // This is in tiles + to = ty * 160 + (int)(tx * 0.5); // This is in pixels... + if (jlUtilIsOdd(to)) to--; //...and must be even for (y=0; y<8; y++) { for (x=0; x<4; x++) { @@ -210,21 +212,23 @@ void jlDrawBlit8x8a(jlSurfaceT source, jint16 cx1, jint16 cy1, jint16 cx2, jint1 void jlDrawBlitMap(jint16 startX, jint16 startY, jint16 width, jint16 height, byte *mapData, juint16 stride, jlSurfaceT source) { - // startX = start tile for drawing - // startY = start tile for drawing - // width = tiles to draw horizontally - // height = tiles to draw vertically + // startX = start tile for drawing - in pixels + // startY = start tile for drawing - in pixels + // width = tiles to draw horizontally - in tiles + // height = tiles to draw vertically - in tiles // mapData = pointer to tile x/y pairs to draw // stride = number of tile bytes to skip in the mapData for every horizontal line - // tiles = sta to fetch tile data from + // tiles = surface to fetch tile data from jint16 x; jint16 y; byte tileX; byte tileY; juint16 offset = 0; + jint16 endX = width * 8 + startX; + jint16 endY = height * 8 + startY; - for (y=startY; y> 8) | (juint16)((twoBytes) << 8) -#define jlStaSurfaceGet(sta) ((jlSurfaceT)sta->pixels) - - void jlDisplayBorder(jlBorderColorsE color); void jlDisplayPresent(void); -void jlDrawBlit8x8(jlSurfaceT source, jint16 cx1, jint16 cy1, jint16 cx2, jint16 cy2); -void jlDrawBlit8x8a(jlSurfaceT source, jint16 cx1, jint16 cy1, jint16 cx2, jint16 cy2, byte offset); +void jlDrawBlit8x8(jlSurfaceT source, jint16 sx, jint16 sy, jint16 tx, jint16 ty); +void jlDrawBlit8x8a(jlSurfaceT source, jint16 sx, jint16 sy, jint16 tx, jint16 ty, byte offset); void jlDrawBlitMap(jint16 startX, jint16 startY, jint16 width, jint16 height, byte *mapData, juint16 stride, jlSurfaceT source); void jlDrawBox(jint16 x1, jint16 y1, jint16 x2, jint16 y2); void jlDrawBoxFilled(jint16 x1, jint16 y1, jint16 x2, jint16 y2); @@ -281,7 +277,9 @@ void jlStaFree(jlStaT *sta); #define jlStaLoad(sta, filename) _jlStaLoad((jlStaT **)&(sta), filename) // Syntatic Sugar bool _jlStaLoad(jlStaT **sta, char *filename); bool jlStaSave(jlStaT *sta, char *filename); +#define jlStaSurfaceGet(sta) ((jlSurfaceT)sta->pixels) +#define jlUtilByteSwap(twoBytes) ((juint16)((twoBytes) & 0xff) >> 8) | (juint16)((twoBytes) << 8) void jlUtilDie(const char *why, ...) __attribute__((noreturn)); void jlUtilIdle(void); #define jlUtilIsOdd(x) (((x & 1) == 1) ? true : false) diff --git a/joeylib/src/test.c b/joeylib/src/test.c index c69a49d..491de1d 100644 --- a/joeylib/src/test.c +++ b/joeylib/src/test.c @@ -32,8 +32,8 @@ segment "testapp"; #endif -extern jint16 asmTest(jlSurfaceT source); -extern void asmDrawLine(jlSurfaceT target, jint16 color, jint16 x1, jint16 y1, jint16 x2, jint16 y2); +//extern jint16 asmTest(jlSurfaceT source); +//extern void asmDrawLine(jlSurfaceT target, jint16 color, jint16 x1, jint16 y1, jint16 x2, jint16 y2); // Font hacking! @@ -41,6 +41,8 @@ __attribute__((__format__ (__printf__, 4, 0))) void printAt(jlStaT *font, jint16 cx, jint16 cy, const char *what, ...) { jint16 x; jint16 y; + jint16 tx; + jint16 ty; jint16 counter; char msg[40]; // Very short messages (screen width). Be careful! va_list va; @@ -49,30 +51,32 @@ void printAt(jlStaT *font, jint16 cx, jint16 cy, const char *what, ...) { vsprintf(msg, what, va); va_end(va); + tx = cx * 8; + ty = cy * 8; + for (counter=0; counter<(int)strlen(msg); counter++) { x = (msg[counter] - ' ') % 40; y = (msg[counter] - ' ') / 40; - jlDrawBlit8x8(jlStaSurfaceGet(font), x, y, counter + cx, cy); + jlDrawBlit8x8(jlStaSurfaceGet(font), x, y, tx, ty); + tx += 8; } } -int main(void) { +void lineTest(void) { - jlStaT *kanga = NULL; - jlStaT *font = NULL; - jint16 y; - jint16 phase = 0; - jint16 x2 = 0; - jint16 y2 = 0; - jint16 ox = 0; - jint16 oy = 0; - jint16 op = 0; - jint16 color = 15; - jint16 nextColor = 1; - char what[32]; - - jlUtilStartup("JoeyLib Test"); + jlStaT *kanga = NULL; + jlStaT *font = NULL; + jint16 y; + jint16 phase = 0; + jint16 x2 = 0; + jint16 y2 = 0; + jint16 ox = 0; + jint16 oy = 0; + jint16 op = 0; + jint16 color = 15; + jint16 nextColor = 1; + char what[32]; if (!jlStaLoad(kanga, "kanga")) jlUtilDie("Unable to load kanga.sta!"); if (!jlStaLoad(font, "font")) jlUtilDie("Unable to load font.sta!"); @@ -92,11 +96,13 @@ int main(void) { printAt(font, 1, y++, "Drawing %s ", what); jlDrawColorSet((byte)color); + /* if (phase < 2) { asmDrawLine(_jlDrawTargetActual, _jlDrawColor, x2, y2, 319-x2, 199-y2); } else { asmDrawLine(_jlDrawTargetActual, _jlDrawColor, 319-x2, 199-y2, x2, y2); } + */ ox = x2; oy = y2; op = phase; @@ -142,11 +148,13 @@ int main(void) { jlDisplayPresent(); jlDrawColorSet((byte)0); + /* if (op < 2) { asmDrawLine(_jlDrawTargetActual, _jlDrawColor, ox, oy, 319-ox, 199-oy); } else { asmDrawLine(_jlDrawTargetActual, _jlDrawColor, 319-ox, 199-oy, ox, oy); } + */ color = nextColor; nextColor++; @@ -160,6 +168,47 @@ int main(void) { jlStaFree(font); jlStaFree(kanga); +} + + +void blitTest(void) { + jlStaT *font = NULL; + jint16 y; + jint16 x; + + if (!jlStaLoad(font, "font")) jlUtilDie("Unable to load font.sta!"); + + jlStaDisplay(font); + jlDisplayPresent(); + jlKeyWaitForAny(); + + jlDrawColorSet(1); + jlDrawClear(); + jlPaletteSet(15, 15, 15, 15); + + y = 91; + while (!jlKeyPressed()) { + for (x=0; x<319-8; x++) { + jlDrawBlit8x8(jlStaSurfaceGet(font), 6, 3, x, y); + printAt(font, 1, 1, "Drawing at %d x %d ", x, y); + jlDisplayPresent(); + jlDrawBlit8x8(jlStaSurfaceGet(font), 0, 0, x, y); + if (jlKeyPressed()) { + break; + } + } + } + jlKeyRead(); + + jlStaFree(font); +} + + +int main(void) { + jlUtilStartup("JoeyLib Test"); + + //lineTest(); + blitTest(); jlUtilShutdown(); }