Game Duenix for Amiga computers/PutPixel.s
Jump to navigation
Jump to search
;------------------------------------------------------------------------------
; DrawPixel - for Duenix for the Amiga
;------------------------------------------------------------------------------
; A set of procedures to draw 1 and 2x2 pixels of a given color.
; It also supports drawing a big (2x2) pixel with conditionally present
; dark boundary pixels around it.
; The logic deals with 5 bitplans; placing a pixel means modifying
; the corresponding bit in each of the 5 bitplans.
; The job seems rather trivial; one has to wonder why doing the same
; in AMOS was too slow (2024).
; This is Motorola 68000 assembly for the Amiga.
;------------------------------------------------------------------------------
;----------------------------------------------------------
; Interface variables
;----------------------------------------------------------
Bitplan0 dc.l 0,0,0,0 ;Addresses of bitplans 0-3
Bitplan4 dc.l 0,0,0,0 ;Address of bitplan 4 and three dummy zeros
pq_x_addr dc.l 0 ;Pixel queue x address
pq_y_addr dc.l 0 ;Pixel queue y address
pq_colour_addr dc.l 0 ;Pixel queue color address
pq_top dc.l 0 ;Top index of the item in the pixel queue
putpix_type dc.b 0
dc.b 0,0,0
;----------------------------------------------------------
; Entry points for procedures
;----------------------------------------------------------
bra Draw_queue_of_pixels
bra Draw_Small_Pixel_Conditioned
bra Draw_Big_Pixel_Conditioned
bra DSP_Conditioned_BigScreen
bra DBP_Conditioned_BigScreen
;----------------------------------------------------------
; Procedure Draw_One_Pixel_BigScreen
; Procedure Draw_One_Pixel
;----------------------------------------------------------
; d0: xcoord (input, does not change)
; d1: ycoord (input, does not change)
; d2: color (input, does not change)
; more input: Bitplan0
;
; used registers: d0-d7 but for d6, a0, a1, a2
;----------------------------------------------------------
Draw_One_Pixel_BigScreen
Move.l d0,d3
Lsr.w #3,d3
Move.l d1,d4
Mulu #80,d4
Add.l d4,d3
Move.l d3,a0 ;a0 := ycoord * 80 + xcoord / 8, which is the offset of the pixel address
bra dop_address_known
Draw_One_Pixel
Move.l d0,d3
Lsr.w #3,d3
Move.l d1,d4
Mulu #40,d4
Add.l d4,d3
Move.l d3,a0 ;a0 := ycoord * 40 + xcoord / 8, which is the offset of the pixel address
dop_address_known
Move.l d0,d3
And.l #7,d3
Sub.l #7,d3
Neg.l d3 ;d3 := 7 - (xcoord band 0b111), which is the bit number
Lea Bitplan0(pc),a1 ;a1 := Bitplan0 address
Moveq #4,d5 ;d5 := bitplan number, and a loop control register (we have 5 bitplans)
Move.l d2,d7 ;d7 := color
dop_Loop_Start
Move.l (a1)+,a2 ;a2 := current bitplan address
Add.l a0,a2
Move.b (a2),d4 ;d4 := the value of the byte of the pixel in the bitplane
Bclr.l d3,d4
Btst #0,d7
Beq dop_Zero
Bset.l d3,d4 ;clear the pixel bit or set it to 1 as applicable
dop_Zero
Move.b d4,(a2) ;write d4 back to the bitplane
Lsr.b #1,d7
DBra d5,dop_Loop_Start
Rts
;--------------------------------------------------------------
; Procedure Draw_Conditioned_Pixel_BigScreen
; Procedure Draw_Conditioned_Pixel
; DCP: Draw conditioned pixel.
; Draw using the color of 1.
; "conditioned" means draw the pixel only if its bitplan 4
; bit is empty.
;--------------------------------------------------------------
; d0: xcoord
; d1: ycoord
;-------------------------------------------------------------
Draw_Conditioned_Pixel_BigScreen
Move.l d0,d3
Lsr.w #3,d3 ;d3 := xcoord / 8
Move.l d1,d4
Mulu #80,d4 ;d4 := ycoord * 80
Add.l d4,d3
Move.l d3,a0 ;a0 := ycoord * 80 + xcoord / 8, which is offset of the pixel address
bra dcp_address_known
Draw_Conditioned_Pixel
Move.l d0,d3
Lsr.w #3,d3 ;d3 := xcoord / 8
Move.l d1,d4
Mulu #40,d4 ;d4 := ycoord * 40
Add.l d4,d3
Move.l d3,a0 ;a0 := ycoord * 40 + xcoord / 8, which is offset of the pixel address
dcp_address_known
Move.l d0,d3
And.l #7,d3
Sub.l #7,d3
Neg.l d3 ;d3 := 7 - (xcoord band 0b111), which is the bit number
Move.l Bitplan4(pc),a1
Btst.b d3,(a1,a0.l)
Bne dcp_Finished ;If bitplan 4 is non-zero, do not draw anything
Lea Bitplan0(pc),a1 ;a1 := Bitplan0 address
;The first round outside of the loop
Move.l (a1)+,a2
Bset.b d3,(a2,a0.l)
Moveq #2,d2 ;Only 3 bitplans remain
dcp_Loop_Start
Move.l (a1)+,a2
Bclr.b d3,(a2,a0.l)
DBra d2,dcp_Loop_Start
dcp_Finished
Rts
;--------------------------------------
; Procedure DSP_Conditioned_BigScreen
; DSP: Draw small pixel
;--------------------------------------
DSP_Conditioned_BigScreen
;Draw classical pixel
Bsr Draw_One_Pixel_BigScreen
;Draw boundary pixels
Subq #1,d1
Bsr Draw_Conditioned_Pixel_BigScreen
Addq #1,d0
Addq #1,d1
Bsr Draw_Conditioned_Pixel_BigScreen
Addq #1,d1
Subq #1,d0
Bsr Draw_Conditioned_Pixel_BigScreen
Subq #1,d0
Subq #1,d1
Bsr Draw_Conditioned_Pixel_BigScreen
Rts
Draw_Small_Pixel_Conditioned
;Draw classical pixel
Bsr Draw_One_Pixel
;Draw boundary pixels
Subq #1,d1
Bsr Draw_Conditioned_Pixel
Addq #1,d0
Addq #1,d1
Bsr Draw_Conditioned_Pixel
Addq #1,d1
Subq #1,d0
Bsr Draw_Conditioned_Pixel
Subq #1,d0
Subq #1,d1
Bsr Draw_Conditioned_Pixel
Rts
;--------------------------------------
; Procedure DBP_Conditioned_BigScreen
; DBP: Draw big pixel.
; The boundary pixels are drawn in
; color 1 and are drawn only
; if the pixel being overwritten
; has color less than 16.
;--------------------------------------
DBP_Conditioned_BigScreen
;Draw classical pixel
Bsr Draw_Big_Pixel_BigScreen
;Draw boundary pixels
Subq #1,d1
Bsr Draw_Conditioned_Pixel_BigScreen
Addq #1,d0
Bsr Draw_Conditioned_Pixel_BigScreen
Addq #1,d0
Addq #1,d1
Bsr Draw_Conditioned_Pixel_BigScreen
Addq #1,d1
Bsr Draw_Conditioned_Pixel_BigScreen
Addq #1,d1
Subq #1,d0
Bsr Draw_Conditioned_Pixel_BigScreen
Subq #1,d0
Bsr Draw_Conditioned_Pixel_BigScreen
Subq #1,d0
Subq #1,d1
Bsr Draw_Conditioned_Pixel_BigScreen
Subq #1,d1
Bsr Draw_Conditioned_Pixel_BigScreen
Rts
Draw_Big_Pixel_Conditioned
;Draw classical pixel
Bsr Draw_Big_Pixel
;Draw boundary pixels
Subq #1,d1
Bsr Draw_Conditioned_Pixel
Addq #1,d0
Bsr Draw_Conditioned_Pixel
Addq #1,d0
Addq #1,d1
Bsr Draw_Conditioned_Pixel
Addq #1,d1
Bsr Draw_Conditioned_Pixel
Addq #1,d1
Subq #1,d0
Bsr Draw_Conditioned_Pixel
Subq #1,d0
Bsr Draw_Conditioned_Pixel
Subq #1,d0
Subq #1,d1
Bsr Draw_Conditioned_Pixel
Subq #1,d1
Bsr Draw_Conditioned_Pixel
Rts
;================================================
; Second, perhaps better take at big pixel
;================================================
;------------------------------------------------
; Procedure Draw_Big_Pixel_BigScreen
;------------------------------------------------
; d0: xcoord
; d1: ycoord
; d2: color
; used: d3, d4, d6, a0
;------------------------------------------------
Draw_Big_Pixel_BigScreen
Move.l d0,d3
Lsr.w #3,d3 ;d3 := xcoord / 8
Move.l d1,d4
Mulu #80,d4 ;d4 := ycoord * 80
Add.l d4,d3
Move.l d3,a0 ;a0 := xcoord / 8 + ycoord * 80
Move.l d0,d4
And.w #$7,d4 ;d4 := xcoord band 0b111 (the bit number)
Move.w #$C000,d3
Lsr.w d4,d3 ;d3 := 0xC000 >> (xcoord band 0b111), which is the oring word
Move.w d3,d6
Eor.w #$FFFF,d6 ;d6 := oring word XOR FFFF, which is the anding word
Bsr dbp_Double_Pixel ;using a0, d2, d3 and d6
Add #80,a0
Bsr dbp_Double_Pixel ;using a0, d2, d3 and d6
Rts
;------------------------------------------------
; Procedure Draw_Big_Pixel
; Draws a "big pixel" consisting of 2x2 pixels
;------------------------------------------------
; d0: xcoord
; d1: ycoord
; d2: color
; used: d3, d4, d6, a0
;------------------------------------------------
Draw_Big_Pixel
Move.l d0,d3
Lsr.w #3,d3 ;d3 := xcoord / 8
Move.l d1,d4
Mulu #40,d4 ;d4 := ycoord * 40
Add.l d4,d3
Move.l d3,a0 ;a0 := xcoord / 8 + ycoord * 40
Move.l d0,d4
And.w #$7,d4 ;d4 := xcoord band 0b111 (the bit number)
Move.w #$C000,d3
Lsr.w d4,d3 ;d3 := 0xC000 >> (xcoord band 0b111), which is the oring word
Move.w d3,d6
Eor.w #$FFFF,d6 ;d6 := oring word XOR FFFF, which is the anding word
Bsr dbp_Double_Pixel ;using a0, d2, d3 and d6
Add #40,a0
Bsr dbp_Double_Pixel ;using a0, d2, d3 and d6
Rts
;------------------------------------------------------------------------------
; Procedure dbp_Double_Pixel
; Draws two pixels horizontally next to each other. To be called two times,
; to draw the complete 2x2 big pixel.
;------------------------------------------------------------------------------
; a0: offset of the word to be modified, against the base of the bitplans
; d2: color
; d3: oring word
; d6: anding word
;------------------------------------------------------------------------------
dbp_Double_Pixel
Lea Bitplan0(pc),a1 ;a1 := Bitplan0
Moveq #4,d5 ;d5 := bitplan number, and a loop control register (we have 5 bitplans)
Move.l d2,d7 ;d7 := color
dbp_Loop_Start
Move.l (a1)+,a2 ;a2 := a1; a1 += 1
Add.l a0,a2 ;a2 := start of the current bitplan + offset of the byte to be modified
Move.w (a2),d4 ;d4 := content of the byte to be modified
And.w d6,d4
Btst #0,d7
Beq dbp_Zero
Or.w d3,d4
dbp_Zero
Move.w d4,(a2) ;write d4 back to the bitplane
Lsr.b #1,d7
DBra d5, dbp_Loop_Start
Rts
;============================================================
;------------------------------------------------
; Procedure Draw_queue_of_pixels
;------------------------------------------------
; input:
; pq_x_addr
; pq_y_addr
; pq_colour_addr
; pq_top
; putpix_type
; local:
; d0, d1, d2, d3, a0
; a6: index of the current element in the queue
;------------------------------------------------
Draw_queue_of_pixels
Move.l pq_x_addr(pc),a3
Move.l pq_y_addr(pc),a4
Move.l pq_colour_addr(pc),a5
Move.l #-1,a6 ;for each item in the queue (d6 := queue_item_idx)
dq_Loop
Addq #1,a6
Move.l pq_top(pc),a0
Cmp.l (a0),a6
Bge dq_finished ;if queue_item_idx >= pq_top: go to dq_finished
Move.l a6,d0
Asl.w #2,d0
Move.l (a5,d0),d2
Move.l (a4,d0),d1
Move.l (a3,d0),d0
Moveq #0,d3
Move.b putpix_type(pc),d3
Lea.l putpix(pc),a0
Jsr (a0,d3)
Bra dq_Loop
dq_finished
Rts
putpix
Bra Draw_Small_Pixel_Conditioned
Bra Draw_Big_Pixel_Conditioned
Bra DSP_Conditioned_BigScreen
Bra DBP_Conditioned_BigScreen