First attempt at masked blit

This commit is contained in:
alpine9000 2016-03-04 11:12:30 +11:00
parent a1ec92dbeb
commit 5da42485ee
5 changed files with 239 additions and 0 deletions

22
007.masked_blit/Makefile Normal file
View File

@ -0,0 +1,22 @@
MODULE=masked_blit.s
FLOPPY=bin/mask_blit.adf
IMAGEDATA=out/image-palette.s out/image.bin
IMAGEFILE=../assets/mission-beach.png
BOB_BASE=out/emoji
BOB_IMAGEDATA=$(BOB_BASE).bin $(BOB_BASE)-mask.bin
BOB_IMAGEFILE=../assets/emoji.png
EXTRA=$(IMAGEDATA) $(BOB_IMAGEDATA)
SHARED_PALETTE_BASE=out/shared-palette
SHARED_PALETTE=$(SHARED_PALETTE_BASE).pal
include ../base.mk
$(SHARED_PALETTE): $(IMAGEFILE) $(BOB_IMAGEFILE)
$(IMAGECON) --input $(IMAGEFILE),$(BOB_IMAGEFILE) --output $(SHARED_PALETTE_BASE) --colors 32 --quantize --output-palette
$(IMAGEDATA): $(IMAGECON) $(IMAGEFILE) $(SHARED_PALETTE)
$(IMAGECON) --input $(IMAGEFILE) --output out/image --output-bitplanes --output-palette-asm --use-palette $(SHARED_PALETTE)
$(BOB_IMAGEDATA): $(IMAGECON) $(BOB_IMAGEFILE) $(SHARED_PALETTE)
$(IMAGECON) --input $(BOB_IMAGEFILE) --output $(BOB_BASE) --output-bitplanes --use-palette $(SHARED_PALETTE)
$(IMAGECON) --input $(BOB_IMAGEFILE) --output $(BOB_BASE) --output-mask --quantize

54
007.masked_blit/README.md Normal file
View File

@ -0,0 +1,54 @@
perform a masked blit
=====================
Extending [006.simple_blit](../006.simple_blit), we now add a mask to the blit.
Using the "cookie-cut" blitter logic funtion we set up the blitter to use all four DMA channels.
[From the hardware manual](http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_guide/node011D.html):
> To draw the car, we might use the A DMA channel to fetch the car mask,
> the B DMA channel to fetch the actual car data, the C DMA channel to
> fetch the background, and the D DMA channel to write out the new image.
```
A = mask
B = blitter object (sprite)
C = background
D = destination (background)
```
Now we calculate the [logic function min term](http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_guide/node011C.html:
blitter logic function minterm truth table
------------------------------------------
We fill in the desired logic values in the D column. In this case D is set if:
* The mask bit is set and the bob bit is set
* The mask bit is not set and the background bit is set
|A(mask)|B(bob)|C(bg)| D(dest)|
|-------|------|-----|--------|
|0|0|0|0|
|0|0|1|1|
|0|1|0|0|
|0|1|1|1|
|1|0|0|0|
|1|0|1|0|
|1|1|0|1|
|1|1|1|1|
Then we read D column from bottom up to give us the logic function minterm:
```
11001010 = $ca
```
This is then ready to be used in the [BLTCON0](http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_guide/node001A.html) register setup.
[imagecon](../tools/imagecon) generates the interleaved mask bitplanes for the A channel.
We then blit the sprite to the background and notice it now has a shape!
[Download disk image](bin/mask_blit.adf?raw=true)
Screenshot:
![Screenshot](screenshot.png?raw=true)

Binary file not shown.

View File

@ -0,0 +1,163 @@
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
BOB_WIDTH equ 64
BOB_HEIGHT equ 64
BOB_WIDTH_BYTES equ BOB_WIDTH/8
BOB_WIDTH_WORDS equ BOB_WIDTH/16
BOB_XPOS equ 16
BOB_YPOS equ 16
BOB_XPOS_BYTES equ (BOB_XPOS)/8
entry:
;; custom chip base globally in a6
lea CUSTOM,a6
move #$7ff,DMACON(a6) ; disable all dma
move #$7fff,INTENA(a6) ; disable all interrupts
include "out/image-palette.s"
if 0
;; reset color registers to white to prevent startup flicker
move.l #32,d0
lea COLOR00(a6),a0
.loop:
move.w #$FFF,(a0)
addq #2,a0
dbra d0,.loop
endif
;; 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
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
;; BLTCON? configuration
;; http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_guide/node011C.html
;; blitter logic function minterm truth table
;; fill in D column for desired function
;; A(mask) B(bob) C(bg) D(dest)
;; - - - -
;; 0 0 0 0
;; 0 0 1 1
;; 0 1 0 0
;; 0 1 1 1
;; 1 0 0 0
;; 1 0 1 0
;; 1 1 0 1
;; 1 1 1 1
;; read D column from bottom up = 11001010 = $ca
;; this is used in the LF? bits
BLIT_LF_MINTERM equ $ca
BLIT_A_SOURCE_SHIFT equ 0
BLIT_DEST equ $100
BLIT_SRCC equ $200
BLIT_SRCB equ $400
BLIT_SRCA equ $800
BLIT_ASHIFTSHIFT equ 12 ;Bit index of ASH? bits
BLIT_BLTCON1 equ 0 ;BSH?=0, DOFF=0, EFE=0, IFE=0, FCI=0, DESC=0, LINE=0
doblit:
movem.l d0-a6,-(sp)
bsr blitWait
move.w #(BLIT_SRCA|BLIT_SRCB|BLIT_SRCC|BLIT_DEST|BLIT_LF_MINTERM|BLIT_A_SOURCE_SHIFT<<BLIT_ASHIFTSHIFT),BLTCON0(A6)
move.w #BLIT_BLTCON1,BLTCON1(a6)
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,BLTBMOD(a6) ; B modulo=bytes to skip between lines
move.w #SCREEN_WIDTH_BYTES-BOB_WIDTH_BYTES,BLTCMOD(a6) ;C modulo
move.w #SCREEN_WIDTH_BYTES-BOB_WIDTH_BYTES,BLTDMOD(a6) ;D modulo
move.l #emojiMask,BLTAPTH(a6) ; mask bitplane
move.l #emoji,BLTBPTH(a6) ; bob bitplane
move.l #bitplanes+BOB_XPOS_BYTES+(SCREEN_WIDTH_BYTES*SCREEN_BIT_DEPTH*BOB_YPOS),BLTCPTH(a6) ;background top left corner
move.l #bitplanes+BOB_XPOS_BYTES+(SCREEN_WIDTH_BYTES*SCREEN_BIT_DEPTH*BOB_YPOS),BLTDPTH(a6) ;destination top left corner
move.w #(BOB_HEIGHT*SCREEN_BIT_DEPTH)<<6|(BOB_WIDTH_WORDS),BLTSIZE(a6) ;rectangle size, starts blit
movem.l (sp)+,d0-a6
rts
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
dc.l $fffffffe
bitplanes:
incbin "out/image.bin"
emoji:
incbin "out/emoji.bin"
emojiMask:
incbin "out/emoji-mask.bin"

BIN
assets/emoji.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB