;*** Lines with the Blitter

;Custom chip register

INTENA  = $9A   ;Interrupt enable register (write)
DMACON  = $96   ;DMA-Control register (write)
DMACONR = $2    ;DMA-Control register (read)
COLOR00 = $180  ;Color palette register
VHPOSR  = $6    ;Position (read)

;Copper Register

COP1LC  = $80   ;Addresse of 1st. Copper-List
COP2LC  = $84   ;Addersse of 2nd. Copper-List
COPJMP1 = $88   ;Jump to  Copper-List 1
COPJMP2 = $8a   ;Jump to Copper-List 2

;Bitplane Register

BPLCON0 = $100  ;Bitplane control register 0
BPLCON1 = $102  ;1 (Scroll value)
BPLCON2 = $104  ;2 (Sprite<>Playfield Priority)
BPL1PTH = $0E0  ;Pointer to 1st. bitplane
BPL1PTL = $0E2  ;
BPL1MOD = $108  ;Modulo value for odd Bit-Planes
BPL2MOD = $10A  ;Modulo value for even Bit-Planes
DIWSTRT = $08E  ;Start of screen window
DIWSTOP = $090  ;End of screen window
DDFSTRT = $092  ;Bit-Plane DMA Start
DDFSTOP = $094  ;Bit-Plane DMA Stop

;Blitter Register

BLTCON0 = $40   ;Blitter control register 0 (ShiftA,Usex,LFx)
BLTCON1 = $42   ;Blitter control register 1 (ShiftB,misc. Bits)
BLTCPTH = $48   ;Pointer to source C
BLTCPTL = $4a
BLTBPTH = $4c   ;Pointer to source B
BLTBPTL = $4e 
BLTAPTH = $50   ;Pointer to source A
BLTAPTL = $52
BLTDPTH = $54   ;Pointer to targer data D
BLTDPTL = $56
BLTCMOD = $60   ;Modulo value for source C
BLTBMOD = $62   ;Modulo value for source B
BLTAMOD = $64   ;Modulo value for source A
BLTDMOD = $66   ;Modulo value for target D
BLTSIZE = $58   ;HBlitter window width/height
BLTCDAT = $70   ;Source C data register
BLTBDAT = $72   ;Source B data register
BLTADAT = $74   ;Source A data register
BLTAFWM = $44   ;Mask for first data word from source A
BLTALWM = $46   ;Mask for first data word from source B

;CIA-A Port register A (Mouse key)

CIAAPRA = $bfe001 

;Exec Library Base Offsets

OpenLibrary = -30-522 ;LibName,Version/a1,d0
Forbid      = -30-102
Permit      = -30-108
AllocMem    = -30-168 ;ByteSize,Requirements/d0,d1
FreeMem     = -30-180 ;MemoryBlock,ByteSize/a1,d0

;Graphics Library Base Offsets

OwnBlitter    = -30-426
DisownBlitter = -30-432

;graphics base

StartList = 38

;other Labels

Execbase   = 4
Planesize  = 80*200      ;Bitplane size: 80 Bytes by 200 lines
Planewidth = 80
CLsize     = 3*4         ;The Copper-List contains 3 commands
Chip       = 2           ;allocate Chip-RAM
Clear      = Chip+$10000 ;Clear Chip-RAM first

;*** Initialization ***

Start:

;A;llocate memory for bit plane

 move.l Execbase,a6
 move.l #Planesize,d0    ;Memory requirment for bit plane
 move.l #clear,d1
 jsr    AllocMem(a6)     ;Allocate memory
 move.l d0,Planeadr
 beq    Ende             ;Error! -> End

;Allocate memory for Copper-List

 moveq  #Clsize,d0
 moveq  #chip,d1
 jsr    AllocMem(a6)
 move.l d0,CLadr
 beq    FreePlane        ;Error! -> FreePlane

;Create Copper-List

 move.l d0,a0            ;Address of Copper-List from a0
 move.l Planeadr,d0      ;Address of Bitplane
 move.w #bpl1pth,(a0)+   ;First Copper coommand in RAM
 swap   d0
 move.w d0,(a0)+         ;Hi-Word of Bit plane address in RAM
 move.w #bpl1ptl,(a0)+   ;second command in RAM
 swap   d0
 move.w d0,(a0)+         ;Lo-Word of  Bitplane address in RAM
 move.l #$fffffffe,(a0)  ;End of Copper-List

;Allocate Blitter

 move.l #GRname,a1
 clr.l  d0
 jsr    OpenLibrary(a6)
 move.l a6,-(sp)         ;ExecBase from the Stack
 move.l d0,a6            ;GraphicsBase from a6
 move.l a6,-(sp)         ;and from the Stack
 jsr    OwnBlitter(a6)   ;Take over Blitter

;*** Main program ***

;DMA and Task-Switching off

 move.l 4(sp),a6         ;ExecBase to a6
 jsr    forbid(a6)       ;Task-Switching off
 lea    $dff000,a5
 move.w #$03e0,dmacon(a5)

;Copper initialization

 move.l CLadr,cop1lc(a5)
 clr.w  copjmp1(a5)

;Set color

 move.w #$0000,color00(a5)   ;Black background
 move.w #$0fa0,color00+2(a5) ;Yellow line

;Playfield initialization

 move.w #$2081,diwstrt(a5)   ;20,129
 move.w #$20c1,diwstop(a5)   ;20,449
 move.w #$003c,ddfstrt(a5)   ;Normal  Hires Screen
 move.w #$00d4,ddfstop(a5)
 move.w #%1001001000000000,bplcon0(a5)
 clr.w  bplcon1(a5)
 clr.w  bplcon2(a5)
 clr.w  bpl1mod(a5)
 clr.w  bpl2mod(a5)

;DMA on
 move.w #$83C0,dmacon(a5)

;Draw lines

;Determine start values:

 move.l Planeadr,a0      ;Constant parameter for DrawLine
 move.w #Planewidth,a1   ;into correct register
 move.w #255,a3          ;Size of  Bitplane in Register
 move.w #639,a4
 move.w #$0303,d7        ;Start pattern

Loop:  rol.w #2,d7       ;Shift pattern
 move.w d7,a2            ;Pattern in register for DrawLine

 clr.w  d6               ;Clear loop variable
LoopX:
 clr.w  d1               ;Y1 = 0
 move.w a3,d3            ;Y2 = 255
 move.w d6,d0            ;X1 = Loop variable
 move.w a4,d2
 sub.w  d6,d2            ;X2 = 639-Loop variable

 bsr DrawLine

 addq.w #4,d6           ;Increment loop variable
 cmp.w  a4,d6           ;Test if greater than 639
 ble.s  LoopX           ;if not. continue loop

 clr.w  d6              ;Clear loop variable
LoopY:
 move.w a4,d0           ;X1 = 639
 clr.w  d2              ;X2 = 0
 move.w d6,d1           ;Y1 = loop variable
 move.w a3,d3
 sub.w  d6,d3           ;Y2 = 255-loop variable

 bsr DrawLine           ;Draw line

 addq.w #2,d6           ;Increment loop variable
 cmp.w  a3,d6           ;Is loop variable greater than 255?
 ble.s  LoopY           ;if not, continue loop

 btst   #6,ciaapra      ;Mouse key pressed?
 bne    Loop            ;No, continue

;*** End program ***

;Wait till blitter is ready

Wait:  btst #14,dmaconr(a5)
 bne    Wait

;Activate old Copper-List

 move.l (sp)+,a6       ;Get GraphicsBase from Stack
 move.l StartList(a6),cop1lc(a5)
 clr.w  copjmp1(a5)    ;Activare Startup-Copper-List
 move.w #$8020,dmacon(a5)
 jsr    DisownBlitter(a6)    ;Release blitter
 move.l (sp)+,a6         ;ExecBase from Stack
 jsr    Permit(a6)       ;Task Switching on

;Release memory for Copper-List

 move.l CLadr,a1         ;Set parameter for FreeMem
 moveq  #CLsize,d0
 jsr    FreeMem(a6)      ;Release memory


;Release Bitplane memory

FreePlane:
 move.l Planeadr,a1
 move.l #Planesize,d0
 jsr    FreeMem(a6)

Ende:
 clr.l  d0
 rts                     ;Program end

;Variablen

CLadr:    dc.l 0         ;Address of Copper-List
Planeadr: dc.l 0         ;Address of Bitplane

;Constants

GRname: dc.b "graphics.library",0

 align                   ;even

;*** DrawLine Routine ***
;DrawLine draws a line with the Blitter.
;The following parameters are used:
;d0  =  X1   X-coordinate of Start points
;d1  =  Y1   Y-coordinate of Start points
;d2  =  X2   X-coordinate of End points
;d3  =  Y2   Y-coordinate of End points
;a0 must point to the first word of the bitplane
;a1 contains bitplane width in bytes
;a2 word written directly to mask register
;d4 to d6 are used as work registers
 
DrawLine:
 
;Compute the lines starting address

 move.l a1,d4            ;Width in work register
 mulu   d1,d4            ;Y1 * Bytes per line
 moveq  #-$10,d5         ;No leading characters: $f0
 and.w  d0,d5            ;Bottom four bits masked from X1
 lsr.w  #3,d5            ;Remainder divided by  8
 add.w  d5,d4            ;Y1 * Bytes per line + X1/8
 add.l  a0,d4            ;plus starting address of the Bitplane
                         ;d4 now contains the starting address
                         ;of the line
                         ;Compute octants and deltas

 clr.l  d5               ;Clear work register
 sub.w  d1,d3            ;Y2-Y1  DeltaY from D3
 roxl.b #1,d5            ;shift leading char from DeltaY in d5
 tst.w  d3               ;Restore N-Flag
 bge.s  y2gy1            ;When DeltaY positive, goto y2gy1
 neg.w  d3               ;DeltaY invert (if not positive)
y2gy1:
 sub.w  d0,d2            ;X2-X1  DeltaX to D2
 roxl.b #1,d5            ;Move leading char in DeltaX to d5
 tst.w  d2               ;Restore N-Flag
 bge.s  x2gx1            ;When DeltaX positive, goto x2gx1
 neg.w  d2               ;DeltaX invert (if not  positive)
x2gx1:
 move.w d3,d1            ;DeltaY to d1
 sub.w  d2,d1            ;DeltaY-DeltaX
 bge.s  dygdx            ;When DeltaY > DeltaX, goto dygdx
 exg    d2,d3            ;Smaller Delta goto d2
dygdx: roxl.b #1,d5      ;d5 contains results of 3 comparisons
 move.b Octant_table(pc,d5),d5 ;get matching octants
 add.w  d2,d2            ;Smaller Delta * 2
  
;Test, for end of last blitter operation

WBlit:   btst #14,dmaconr(a5);BBUSY-Bit test
 bne.s   WBlit           ;Wait until equal to 0

 move.w d2,bltbmod(a5)   ;2* smaller Delta to BLTBMOD
 sub.w  d3,d2            ;2* smaller Delta - larger Delta
 bge.s  signnl           ;When 2* small delta > large delta to signnl
 or.b   #$40,d5          ;Sign flag set
signnl: move.w d2,bltaptl(a5) ;2*small delta-large delta in BLTAPTL
 sub.w  d3,d2            ;2* smaller Delta - 2* larger Delta
 move.w d2,bltamod(a5)   ;to BLTAMOD

;Initialization other info

 move.w #$8000,bltadat(a5)
 move.w a2,bltbdat(a5)   ;Mask from a2 in BLTBDAT
 move.w #$ffff,bltafwm(a5)
 and.w  #$000f,d0        ;bottom  4 Bits from  X1
 ror.w  #4,d0            ;to START0-3
 or.w   #$0bca,d0        ;USEx and LFx set
 move.w d0,bltcon0(a5)
 move.w d5,bltcon1(a5)   ;Octant in Blitter
 move.l d4,bltcpth(a5)   ;Start address of line to
 move.l d4,bltdpth(a5)   ;BLTCPT and BLTDPT
 move.w a1,bltcmod(a5)   ;Width of Bitplane in both
 move.w a1,bltdmod(a5)   ;Modulo Registers

;BLTSIZE initialization and Blitter start

 lsl.w  #6,d3            ;LENGTH * 64
 addq.w #2,d3            ;plus (Width = 2)
 move.w d3,bltsize(a5)

 rts

;Octant table with LINE =1:
;The octant table contains code values
;for each octant, shifted to the correct position




Octant_table:

 dc.b 0 *4+1 ;y1<y2, x1<x2, dx<dy = Okt6 
 dc.b 4 *4+1 ;y1<y2, x1<x2, dx>dy = Okt7
 dc.b 2 *4+1 ;y1<y2, x1>x2, dx<dy = Okt5
 dc.b 5 *4+1 ;y1<y2, x1>x2, dx>dy = Okt4
 dc.b 1 *4+1 ;y1>y2, x1<x2, dx<dy = Okt1
 dc.b 6 *4+1 ;y1>y2, x1<x2, dx>dy = Okt0
 dc.b 3 *4+1 ;y1>y2, x1>x2, dx<dy = Okt2
 dc.b 7 *4+1 ;y1>y2, x1>x2, dx>dy = Okt3

 end


