diff --git a/006.simple_blit/Makefile b/006.simple_blit/Makefile new file mode 100644 index 0000000..58668e8 --- /dev/null +++ b/006.simple_blit/Makefile @@ -0,0 +1,18 @@ +MODULE=blit.s +FLOPPY=bin/blit.adf +IMAGEDATA=out/image-copper-list.s out/image.bin +IMAGEFILE=../assets/mission-beach.png +TC_IMAGEDATA=out/tc.bin out/tc-mask.bin +TC_IMAGEFILE=../assets/tc.png +EXTRA=$(IMAGEDATA) $(TC_IMAGEDATA) out/bitblit.s + +include ../base.mk + +out/bitblit.s: bitblit.c + vc -S bitblit.c -o out/bitblit.s + +$(IMAGEDATA): $(IMAGECON) $(IMAGEFILE) + $(IMAGECON) --input $(IMAGEFILE) --output out/image --colors 32 --quantize + +$(TC_IMAGEDATA): $(IMAGECON) $(TC_IMAGEFILE) + $(IMAGECON) --input $(TC_IMAGEFILE) --output out/tc --colors 32 --quantize --output-mask diff --git a/006.simple_blit/README.md b/006.simple_blit/README.md new file mode 100644 index 0000000..08af624 --- /dev/null +++ b/006.simple_blit/README.md @@ -0,0 +1,16 @@ +Display a simple image +====================== + +Building on [trackdisk.device](../000.trackdisk), we now display a simple color image. + +I display a 5 bitplane (32 color) low res image. + +The image data is prepared using a new tool I wrote called [imagecon](../tools/imagecon/imagecon.c). This takes (almost) any 320x256 PNG and using [libimagequant](https://pngquant.org/lib/) it reduces the palette to 32 colors, then dumps out the copper list and interleaved bitplane data ready to be included into [image.s](image.s). + +The original version of this example used [vilcans amiga-startup](https://github.com/vilcans/amiga-startup) as a starting point, however almost all of that code has been replaced as my understanding exanded. + +[Download disk image](bin/image.adf?raw=true) + +Screenshot: + +![Screenshot](screenshot.png?raw=true) diff --git a/006.simple_blit/bin/blit.adf b/006.simple_blit/bin/blit.adf new file mode 100644 index 0000000..8cf5b8b Binary files /dev/null and b/006.simple_blit/bin/blit.adf differ diff --git a/006.simple_blit/bitblit.c b/006.simple_blit/bitblit.c new file mode 100644 index 0000000..564e91c --- /dev/null +++ b/006.simple_blit/bitblit.c @@ -0,0 +1,43 @@ +#include "hardware/custom.h" +#include "hardware/dmabits.h" + +/* +Scrollit: +;; --- scroll! --- +bltoffs =plotY*ScrBpl*3 + +blth =20 +bltw =w/16 + bltskip =0 ;modulo +brcorner=blth*ScrBpl*3-2 + + movem.l d0-a6,-(sp) + lea $dff000,a6 + bsr BlitWait + + move.l #$49f00002,BLTCON0(a6) + move.l #$ffffffff,BLTAFWM(a6) + move.l #Screen+bltoffs+brcorner,BLTAPTH(a6) + move.l #Screen+bltoffs+brcorner,BLTDPTH(a6) + move.w #bltskip,BLTAMOD(a6) + move.w #bltskip,BLTDMOD(a6) + + move.w #blth*3*64+bltw,BLTSIZE(a6) + movem.l (sp)+,d0-a6 + rts +*/ + + + +extern void blitwait(void); + +void bitblit(unsigned* src, unsigned* dest, unsigned sw, unsigned dw, unsigned dx, unsigned dy) +{ + static struct Custom *custom = (struct Custom *)0xDFF000; + + custom->dmacon = (DMAF_SETCLR|DMAF_COPPER|DMAF_RASTER|DMAF_MASTER); + /* + blitwait(); + custom->bltcon0 = 0x49f00002; + custom->bltafwm = 0xffffffff;*/ +} diff --git a/006.simple_blit/blit.s b/006.simple_blit/blit.s new file mode 100644 index 0000000..ac75d9a --- /dev/null +++ b/006.simple_blit/blit.s @@ -0,0 +1,142 @@ + include "../include/registers.i" + include "hardware/dmabits.i" + include "hardware/intbits.i" + +LVL3_INT_VECTOR equ $6c +SCREEN_WIDTH equ 320 +SCREEN_HEIGHT equ 256 +SCREEN_WIDTH_BYTES equ (SCREEN_WIDTH/8) +SCREEN_BIT_DEPTH equ 5 +SCREEN_RES equ 8 ; 8=lo resolution, 4=hi resolution +RASTER_X_START equ $81 ; hard coded coordinates from hardware manual +RASTER_Y_START equ $2c +RASTER_X_STOP equ RASTER_X_START+SCREEN_WIDTH +RASTER_Y_STOP equ RASTER_Y_START+SCREEN_HEIGHT + + public _bitblit + +entry: + ;; custom chip base globally in a6 + lea CUSTOM,a6 + + move #$7ff,DMACON(a6) ; disable all dma + move #$7fff,INTENA(a6) ; disable all interrupts + + ;; bsr.s resetBitplanePointers + ;; reset color registers to white + move.l #32,d0 + lea COLOR00(a6),a0 +.loop: + move.w #$FFF,(a0) + addq #2,a0 + dbra d0,.loop + + ;; set up playfield + move.w #(RASTER_Y_START<<8)|RASTER_X_START,DIWSTRT(a6) + move.w #((RASTER_Y_STOP-256)<<8)|(RASTER_X_STOP-256),DIWSTOP(a6) + + move.w #(RASTER_X_START/2-SCREEN_RES),DDFSTRT(a6) + move.w #(RASTER_X_START/2-SCREEN_RES)+(8*((SCREEN_WIDTH/16)-1)),DDFSTOP(a6) + + move.w #(SCREEN_BIT_DEPTH<<12)|$200,BPLCON0(a6) + move.w #SCREEN_WIDTH_BYTES*SCREEN_BIT_DEPTH-SCREEN_WIDTH_BYTES,BPL1MOD(a6) + move.w #SCREEN_WIDTH_BYTES*SCREEN_BIT_DEPTH-SCREEN_WIDTH_BYTES,BPL2MOD(a6) + + ;; poke bitplane pointers + lea bitplanes(pc),a1 + lea copper(pc),a2 + moveq #SCREEN_BIT_DEPTH-1,d0 +.bitplaneloop: + move.l a1,d1 + move.w d1,2(a2) + swap d1 + move.w d1,6(a2) + lea SCREEN_WIDTH_BYTES(a1),a1 ; bit plane data is interleaved + addq #8,a2 + dbra d0,.bitplaneloop + + ;; install copper list, then enable dma and selected interrupts + lea copper(pc),a0 + move.l a0,COP1LC(a6) + move.w COPJMP1(a6),d0 + move.w #(DMAF_BLITTER|DMAF_SETCLR!DMAF_COPPER!DMAF_RASTER!DMAF_MASTER),DMACON(a6) + move.w #(INTF_SETCLR|INTF_INTEN|INTF_EXTER),INTENA(a6) + + bsr.s doblit + +.mainLoop: + move.w #$02a,d0 ;wait for EOFrame + bsr.s waitRaster + bra.s .mainLoop + + if 0 +resetBitplanePointers: + movem.l d0-a6,-(sp) + lea bitplanes,a1 + lea BPL1PTH(a6),a2 + moveq #SCREEN_BIT_DEPTH,d0 +.bitplaneloop: + move.l a1,(a2) + lea SCREEN_WIDTH_BYTES(a1),a1 ; bit plane data is interleaved + addq #4,a2 + dbra d0,.bitplaneloop + movem.l (sp)+,d0-a6 + rts + endif + +waitRaster: ;wait for rasterline d0.w. Modifies d0-d2/a0. + move.l #$1ff00,d2 + lsl.l #8,d0 + and.l d2,d0 + lea $dff004,a0 +.wr: move.l (a0),d1 + and.l d2,d1 + cmp.l d1,d0 + bne.s .wr + rts + +blitWait: + tst DMACONR(a6) ;for compatibility +.waitblit: + btst #6,DMACONR(a6) + bne.s .waitblit + rts + +doblit: + movem.l d0-a6,-(sp) + lea $dff000,a6 + bsr blitWait + move.l #$09f00000,BLTCON0(a6) ;A->D copy, no shifts, ascending mode + move.l #$ffffffff,BLTAFWM(a6) ;no masking of first/last word + move.w #0,BLTAMOD(a6) ;A modulo=bytes to skip between lines + move.w #0,BLTDMOD(a6) ;D modulo + move.l #bitplanes,BLTAPTH(a6) ;source graphic top left corner + move.l #bitplanes+(SCREEN_WIDTH_BYTES*SCREEN_BIT_DEPTH*SCREEN_HEIGHT/2),BLTDPTH(a6) ;destination top left corner + move.w #SCREEN_WIDTH_BYTES*SCREEN_BIT_DEPTH*SCREEN_HEIGHT/4,BLTSIZE(a6) ;rectangle size, starts blit + movem.l (sp)+,d0-a6 + rts + + include "out/bitblit.s" +copper: + ;; bitplane pointers must be first else poking addresses will be incorrect + dc.w BPL1PTL,0 + dc.w BPL1PTH,0 + dc.w BPL2PTL,0 + dc.w BPL2PTH,0 + dc.w BPL3PTL,0 + dc.w BPL3PTH,0 + dc.w BPL4PTL,0 + dc.w BPL4PTH,0 + dc.w BPL5PTL,0 + dc.w BPL5PTH,0 + + include "out/image-copper-list.s" + + dc.l $fffffffe +bitplanes: + incbin "out/image.bin" + +tc: + incbin "out/tc.bin" +tcMask: + incbin "out/tc-mask.bin" \ No newline at end of file