From bfc7dc093e2ea90ee4efe5d36c2d62af3cff9fb8 Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Mon, 11 May 2020 18:02:43 -0500 Subject: [PATCH] Working on new stencil blitter for IIgs. --- .gitignore | 2 + imgconvert/main.c | 2 +- joeylib/build.sh | 10 ++- joeylib/src/jIIgs.asm | 181 +++++++++++++++++++++++++++++++++++++++--- joeylib/src/jIIgs.c | 50 ++++++------ joeylib/src/jSDL2.c | 40 +--------- joeylib/src/joey.h | 4 +- joeylib/src/test.c | 21 +++-- 8 files changed, 222 insertions(+), 88 deletions(-) diff --git a/.gitignore b/.gitignore index 8b2958e..3ccaf1c 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ notes.txt assets/JoeyLib Logo - 320x200.png assets/JoeyLib Logo.jpg assets/JoeyLib Logo.png +*.stn +*.img diff --git a/imgconvert/main.c b/imgconvert/main.c index 0543e6e..100f51a 100644 --- a/imgconvert/main.c +++ b/imgconvert/main.c @@ -97,7 +97,7 @@ void convertStencil(char *filename, char *basename) { for (int y=0; yh; y++) { for (int x=0; xw; x++) { data <<= 1; - data |= (getPixel(image, x, y) == 0); + data |= (getPixel(image, x, y) != 0); bits++; if (bits > 7) { bytes++; diff --git a/joeylib/build.sh b/joeylib/build.sh index 6baad07..3e02c29 100755 --- a/joeylib/build.sh +++ b/joeylib/build.sh @@ -99,8 +99,9 @@ function doIIgsBuild() { rm "${IMPORT}" 2> /dev/null || true cp "${OUT}/test" "${OUT}/Test#B30000" - cp "${JOEY}/joeylib/joeylib/src/kanga.sta" "${OUT}/kanga.sta#060000" - cp "${JOEY}/joeylib/joeylib/src/font.sta" "${OUT}/font.sta#060000" + cp "${JOEY}/joeylib/joeylib/src/kanga.img" "${OUT}/kanga.img#060000" + cp "${JOEY}/joeylib/joeylib/src/font.img" "${OUT}/font.img#060000" + cp "${JOEY}/joeylib/joeylib/src/font.stn" "${OUT}/font.stn#060000" cp "${JOEY}/joeylib/joeylib/src/music" "${OUT}/music#D50000" cp "${JOEY}/joeylib/joeylib/src/music.w" "${OUT}/music.w#060000" @@ -108,8 +109,9 @@ function doIIgsBuild() { "${CADIUS}" createfolder "${IMPORT}" ${VOL}/data > /dev/null "${CADIUS}" addfile "${IMPORT}" ${VOL} "${JOEY}/dist/IIgs/Tool221#ba0000" > /dev/null "${CADIUS}" addfile "${IMPORT}" ${VOL} "${OUT}/Test#b30000" > /dev/null - "${CADIUS}" addfile "${IMPORT}" ${VOL}/data "${OUT}/kanga.sta#060000" > /dev/null - "${CADIUS}" addfile "${IMPORT}" ${VOL}/data "${OUT}/font.sta#060000" > /dev/null + "${CADIUS}" addfile "${IMPORT}" ${VOL}/data "${OUT}/kanga.img#060000" > /dev/null + "${CADIUS}" addfile "${IMPORT}" ${VOL}/data "${OUT}/font.img#060000" > /dev/null + "${CADIUS}" addfile "${IMPORT}" ${VOL}/data "${OUT}/font.stn#060000" > /dev/null "${CADIUS}" addfile "${IMPORT}" ${VOL}/data "${OUT}/music#D50000" > /dev/null "${CADIUS}" addfile "${IMPORT}" ${VOL}/data "${OUT}/music.w#060000" > /dev/null diff --git a/joeylib/src/jIIgs.asm b/joeylib/src/jIIgs.asm index 3632465..af33dea 100644 --- a/joeylib/src/jIIgs.asm +++ b/joeylib/src/jIIgs.asm @@ -27,8 +27,8 @@ GlobalData data -ScanTable entry - ds 400 ; 400 bytes for scanline offsets +ScTable ds 400 ; 400 bytes for 200 scanline offsets +StTable ds 50 ; 50 bytes for 25 stencil table offsets VblRate ds 2 ; Either 5 or 6 depending on PAL or NTSC. VblTime ds 2 ; Integer Counter end @@ -61,7 +61,7 @@ yc equ 9 ; Y Counter asl a ; y screen location is now in the accumulator tay clc - lda ScanTable,y ; Load byte offset of y position from table + lda ScTable,y ; Load byte offset of y position from table adc t ; Add t to scanline offset sta source ; Offset to start of source pixels @@ -75,7 +75,7 @@ yc equ 9 ; Y Counter 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 + lda ScTable,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 @@ -128,7 +128,7 @@ blitTop ldy source ; Load Y register with source pixel offset ;---------------------------------------- ; Blit an 8x8 block with alpha to (almost) anywhere on a surface. ;---------------------------------------- -asmB88a start +asmB88ax start source equ 1 ; Source Pixels Offset target equ 3 ; Target Pixels Offset @@ -153,7 +153,7 @@ yc equ 11 ; Y Counter asl a ; y screen location is now in the accumulator tay clc - lda ScanTable,y ; Load byte offset of y position from table + lda ScTable,y ; Load byte offset of y position from table adc t ; Add t to scanline offset sta source ; Offset to start of source pixels @@ -175,7 +175,7 @@ yc equ 11 ; Y Counter 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 + lda ScTable,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 @@ -237,6 +237,150 @@ blitTop ldy target ; Load Y register with target pixel offset end +;---------------------------------------- +; Blit an 8x8 block with stencil to (almost) anywhere on a surface. +;---------------------------------------- +asmB88a start + +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 +stenO equ 11 ; Stencil Buffer Offset +stenB equ 12 ; Stencil Buffer Data - bits - two bytes, but we only use one +maskW equ 14 ; Actual mask bytes for pixels + + jsubroutine (4:surface,4:tiles,4:stencil,2:sx,2:sy,2:tx,2:ty),16 + using GlobalData + +; Find offset into tile memory + lda sx ; Multiply sx by 4 to get offset (two pixels per byte) + asl a + asl a + sta t + clc + 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 + tay + clc + lda ScTable,y ; Load byte offset of y position from table + adc t ; Add t to scanline offset + 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 tx + +; Find offset into target surface memory + 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 ScTable,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 + +; Find starting stencil byte + clc + ldy ty ; Vertical cell position + lda StTable,y ; Load offset location of start of this row in the stencil buffer + adc tx ; Add x position to address offset + sta stenO ; Offset to start of mask data + + + lda #0 ; Load 0 into X and Y counters + sta xc + sta yc + +blitTop lda [stenO] ; Load byte at stencil offset + xba ; Shift it into the high byte + sta stenB ; Put it in to the stencil byte + +; Convert stencil byte to mask word (4 pixels) + ldx #4 ; How many pixels to process? + lda #0 ; Initially, the mask word is all zero bits + sta maskW +nextNib lda stenB ; Load stencil byte into accumulator + asl a ; Shift first bit out of stencil byte into C + bcs pixOn ; If C is set, we draw the pixel + lda maskW ; Load mask word into accumulator + asl a ; Shift mask word over a pixel (4 bits) + asl a + asl a + asl a + and #$fff0 ; Do not draw pixel - mask it off + sta maskW ; Store updated mask word + jmp nextPix ; Start next pixel +pixOn lda maskW ; Load mask word into accumulator + asl a ; Shift mask word over a pixel (4 bits) + asl a + asl a + asl a + and #$ffff ; Draw pixel + sta maskW ; Store updated mask word +nextPix dex ; Decrement pixel counter in X + bne nextNib ; Not zero? Do next nibble/pixel + +; Draw four pixels + ldy target ; Load Y register with target pixel offset + lda [surface],y ; Load target pixels + and maskW ; AND with mask word + ldy source ; Load Y register with source pixel offset + ora [tiles],y ; OR with source pixels + 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 target + sta target + clc ; Increment to next pixel source quad + lda #2 + adc source + sta source + clc ; Increment to next stencil byte + lda #1 + adc stenO + sta stenO + + clc + lda xc ; Increment X counter + adc #1 + sta xc + cmp #2 ; End of X pixels? + bcc blitTop ; Nope! + + lda #0 ; Reset X counter + sta xc + clc ; Increment target offset + lda #156 + adc target + sta target + clc ; Increment source offset + lda #156 + adc source + sta source + clc ; Increment stencil mask offset + lda #39 + adc stenO + sta stenO + clc + lda yc ; Increment Y counter + adc #1 + sta yc + cmp #8 ; End of Y pixels? + bcs blitDone ; Yep! + brl blitTop ; Back for more + +blitDone jreturn + end + + ;---------------------------------------- ; Set Border Color ;---------------------------------------- @@ -879,7 +1023,7 @@ temp1 equ 1 lda Yp ; Load accumulator with Y location asl a ; Shift accumulator left (multiply by 2) for word offset into table tay ; Transfer accumulator to y register - lda ScanTable,y ; Look up scan line address offset + lda ScTable,y ; Look up scan line address offset sta temp1 ; Store accumulator (row offset into SHR memory) into temp1 clc ; Clear carry flag lda Xp ; Place X position in accumulator @@ -1100,7 +1244,7 @@ PBoth sta temp3 ; Store accumulator in temp3 lda Yp ; Load accumulator with Y location asl a ; Shift accumulator left (multiply by 2) tay ; Transfer accumulator to y register - lda ScanTable,y ; Look up scan line address offset + lda ScTable,y ; Look up scan line address offset adc temp1 ; Add X position to address with carry tay ; Transfer accumulator to y @@ -1348,13 +1492,24 @@ asmStart start ldy #0 ; Load 0 into y register lda #0 ; Load 0 into accumulator clc ; Clear carry flag -buildTable anop - sta ScanTable,y ; Store accumulator in ScanTable+x - adc #160 ; Add 160 to accumulator +tScan anop + sta ScTable,y ; Store accumulator in ScTable+x + adc #160 ; Add 160 to accumulator (320 pixels / 2 pixels per byte) iny ; Increment y iny ; Increment y cpy #400 ; Compare y to 400 (200 scanlines) - bcc buildTable ; Repeat Scan Table Loop until we do all 200 lines + bcc tScan ; Repeat Scan Table Loop until we do all 200 lines + + ldy #0 ; Load 0 into y register + lda #0 ; Load 0 into accumulator + clc ; Clear carry flag +tSten anop + sta StTable,y ; Store accumulator in StencilTable+x + adc #320 ; Add 320 to accumulator (8 lines * 40 bytes) + iny ; Increment y + iny ; Increment y + cpy #50 ; Compare y to 50 (25 stencil cell offsets) + bcc tSten ; Repeat Stencil Table Loop until we do all 25 cells lda hertz ; Store refresh rate / 10 in VblCount and VblRate sta >VblRate diff --git a/joeylib/src/jIIgs.c b/joeylib/src/jIIgs.c index a7f518f..dd0a685 100644 --- a/joeylib/src/jIIgs.c +++ b/joeylib/src/jIIgs.c @@ -156,6 +156,29 @@ bool jlGameGetButton(byte which) { } +bool _jlImgCreate(jlImgT **img) { + jlImgT *t = (jlImgT *)jlMalloc(sizeof(jlImgT)); + if (t != NULL) { + memset(t, 0, sizeof(jlImgT)); + t->id[0] = 'I'; + t->id[1] = 'M'; + t->id[2] = 'G'; + t->version = 0; + memcpy(t->palette, SHRCOLORS, sizeof(t->palette)); + memcpy(t->pixels, SHRPIXELS, sizeof(t->pixels)); + *img = t; + return true; + } + return false; +} + + +void jlImgDisplay(jlImgT *img) { + memcpy(SHRCOLORS, img->palette, sizeof(img->palette)); + memcpy(SHRPIXELS, img->pixels, sizeof(img->pixels)); +} + + char _jlKeyCheck(char key) { if ((key < 8) || (key > 127)) { key = 0; @@ -206,8 +229,8 @@ void jlPaletteSet(byte index, byte r, byte g, byte b) { } -void jlPaletteSetFromSta(jlStaT *sta) { - memcpy(SHRCOLORS, sta->palette, sizeof(sta->palette)); +void jlPaletteSetFromImg(jlImgT *img) { + memcpy(SHRCOLORS, img->palette, sizeof(img->palette)); } @@ -266,29 +289,6 @@ void jlSoundPlay(jlSoundT *sound) { } -bool _jlStaCreate(jlStaT **sta) { - jlStaT *t = (jlStaT *)jlMalloc(sizeof(jlStaT)); - if (t != NULL) { - memset(t, 0, sizeof(jlStaT)); - t->id[0] = 'S'; - t->id[1] = 'T'; - t->id[2] = 'A'; - t->version = 0; - memcpy(t->palette, SHRCOLORS, sizeof(t->palette)); - memcpy(t->pixels, SHRPIXELS, sizeof(t->pixels)); - *sta = t; - return true; - } - return false; -} - - -void jlStaDisplay(jlStaT *sta) { - memcpy(SHRCOLORS, sta->palette, sizeof(sta->palette)); - memcpy(SHRPIXELS, sta->pixels, sizeof(sta->pixels)); -} - - void jlUtilIdle(void) { // No need to pump the message loop on the IIgs } diff --git a/joeylib/src/jSDL2.c b/joeylib/src/jSDL2.c index c39648d..82cc8c0 100644 --- a/joeylib/src/jSDL2.c +++ b/joeylib/src/jSDL2.c @@ -177,42 +177,6 @@ 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) { - int mo; // Mask offset - int so; // Source Pixel Offset - int to; // Target Pixel Offset - int x; - int y; - jlPixelPairT m; // Mask - jlPixelPairT s; // Source Pixel - jlPixelPairT t; // Target Pixel - jlPixelPairT *pixels = (jlPixelPairT *)source; - jlPixelPairT *target = (jlPixelPairT *)_jlDrawTargetActual; - - // We mask off unused bits in the source tile location so they can be used to hold other data. - 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 - if (jlUtilIsOdd(tx)) tx--; // tx must be even because there are two pixels per byte - to = ty * 160 + (int)(tx * 0.5); // This is in pixels... - - for (y=0; y<8; y++) { - for (x=0; x<4; x++) { - m = pixels[mo++]; - s = pixels[so++]; - t = target[to]; - t.r = (t.r & m.r) | s.r; - t.l = (t.l & m.l) | s.l; - target[to++] = t; - } - mo += 156; - so += 156; - to += 156; - } -} -*/ - - void jlDrawBlit8x8a(jlSurfaceT source, jlStnT *stencil, jint16 sx, jint16 sy, jint16 tx, jint16 ty) { int mo; // Mask offset int so; // Source Pixel Offset @@ -238,11 +202,11 @@ void jlDrawBlit8x8a(jlSurfaceT source, jlStnT *stencil, jint16 sx, jint16 sy, ji s = pixels[so++]; //***FIX*** Another endian order issue. Left & Right are swapped. - if ((stencil->pixels[mo] & (1 << b--)) == 0) { + if ((stencil->pixels[mo] & (1 << b--)) != 0) { t.r = s.r; } - if ((stencil->pixels[mo] & (1 << b--)) == 0) { + if ((stencil->pixels[mo] & (1 << b--)) != 0) { t.l = s.l; } diff --git a/joeylib/src/joey.h b/joeylib/src/joey.h index 687074c..e1b0d33 100644 --- a/joeylib/src/joey.h +++ b/joeylib/src/joey.h @@ -324,7 +324,7 @@ bool _jlVecLoad(jlVecT **vec, char *filename); #ifdef JOEY_IIGS // Inlined functions - asm code extern void asmB88(jlSurfaceT target, jlSurfaceT source, jint16 cx1, jint16 cy1, jint16 cx2, jint16 cy2); -extern void asmB88a(jlSurfaceT target, jlSurfaceT source, jint16 cx1, jint16 cy1, jint16 cx2, jint16 cy2, byte alphaOffset); +extern void asmB88a(jlSurfaceT target, jlSurfaceT source, byte *stencil, jint16 cx1, jint16 cy1, jint16 cx2, jint16 cy2); extern void asmDrawBM(jlSurfaceT target, jint16 startX, jint16 startY, jint16 width, jint16 height, byte *mapData, juint16 stride, jlSurfaceT source); //extern void asmDrawLine(jlSurfaceT target, jint16 color, jint16 x1, jint16 y1, jint16 x2, jint16 y2); extern jint16 asmGetPoint(jlSurfaceT target, jint16 x, jint16 y); @@ -334,7 +334,7 @@ extern void asmPoint(jlSurfaceT target, jint16 color, jint16 x, jint16 y); // Inlined functions #define jlDrawBlit8x8(source, cx1, cy1, cx2, cy2) asmB88(_jlDrawTargetActual, source, cx1, cy1, cx2, cy2) -#define jlDrawBlit8x8a(source, cx1, cy1, cx2, cy2, offset) asmB88a(_jlDrawTargetActual, source, cx1, cy1, cx2, cy2, offset) +#define jlDrawBlit8x8a(source, stencil, cx1, cy1, cx2, cy2) asmB88a(_jlDrawTargetActual, source, (byte *)stencil, cx1, cy1, cx2, cy2) #define jlDrawBlitMap(startX, startY, width, height, mapData, stride, source) asmDrawBM(_jlDrawTargetActual, startX, startY, width, height, (byte *)mapData, stride, source) #define jlDrawPixelGet(x, y) asmGetPoint(_jlDrawTargetActual, x, y) #define jlDrawPixelSet(x, y) asmPoint(_jlDrawTargetActual, _jlDrawColorNibbles, x, y) diff --git a/joeylib/src/test.c b/joeylib/src/test.c index 5018c11..6c1ba35 100644 --- a/joeylib/src/test.c +++ b/joeylib/src/test.c @@ -41,8 +41,8 @@ extern void asmDrawLine(jlSurfaceT target, jint16 color, jint16 x1, jint16 y1 // Font hacking! -__attribute__((__format__ (__printf__, 4, 0))) -void printAt(jlImgT *font, jint16 cx, jint16 cy, const char *what, ...) { +__attribute__((__format__ (__printf__, 5, 0))) +void printAt(jlImgT *font, jlStnT *stencil, jint16 cx, jint16 cy, const char *what, ...) { jint16 x; jint16 y; jint16 tx; @@ -63,7 +63,11 @@ void printAt(jlImgT *font, jint16 cx, jint16 cy, const char *what, ...) { //y = (msg[counter] - ' ') / 40; x = msg[counter] % 40; y = msg[counter] / 40; - jlDrawBlit8x8(jlImgSurfaceGet(font), x, y, tx, ty); + if (stencil) { + jlDrawBlit8x8a(jlImgSurfaceGet(font), stencil, x, y, tx, ty); + } else { + jlDrawBlit8x8(jlImgSurfaceGet(font), x, y, tx, ty); + } tx += 8; } } @@ -99,7 +103,7 @@ void lineTest(void) { while (!jlKeyPressed()) { y = 17; //printAt(font, 1, y++, "R = %d ", asmTest((jlSurfaceT)0x012000)); - printAt(font, 1, y++, "Drawing %s ", what); + printAt(font, NULL, 1, y++, "Drawing %s ", what); jlDrawColorSet((byte)color); if (phase < 2) { @@ -191,6 +195,12 @@ void blitTest(void) { jlDrawClear(); jlPaletteSet(15, 15, 15, 15); + printAt(font, NULL, 1, 2, "%s", "Blitting without stencil buffer."); + printAt(font, stencil, 1, 4, "%s", "Blitting with stencil buffer."); + jlDisplayPresent(); + jlKeyWaitForAny(); + + /* y = 91; while (!jlKeyPressed()) { for (x=0; x<319-8; x++) { @@ -202,7 +212,7 @@ void blitTest(void) { } jlDrawBlit8x8(jlImgSurfaceGet(font), 1, 0, x, y); - printAt(font, 1, 1, "Drawing at %d x %d ", x, y); + printAt(font, NULL, 1, 1, "Drawing at %d x %d ", x, y); jlDisplayPresent(); jlDrawBlit8x8(jlImgSurfaceGet(font), 0, 0, x, y); jlUtilSleep(1); @@ -212,6 +222,7 @@ void blitTest(void) { } } jlKeyRead(); + */ jlStnFree(stencil); jlImgFree(font);