Amiga.org
Operating System Specific Discussions => Amiga OS => Amiga OS -- Development => Topic started by: balrogsoft on August 14, 2006, 04:35:29 PM
-
Hi, i'm trying to learn assembler, i'm using DevPac 3.18, and i only get to work a few of examples, but i have a problem, i have a startup source with a draw line code, it works on my A600, but on my A1200 i got corrupted screen graphics, i got it to work on my A1200 if i remove DIWSTRT, DIWSTOP register data and DDFSTRT and DDFSTOP1 from copper list, but then the line isn't drawed.
Other question, a lot of examples don't work because DevPac don't recognise instruction BLK, is a specific assembler instruction? it can be switched with other instruction compatible with DevPac?
And the last question is about Blitter, to check if the blitter finished the operation, i test bit 6 on $DFF000 address, but i found that some codes test bit 14, and DevPac says that you can test bits 0-7. Why some codes use bit 14?
;************************************************
;* Non-System Draw Line Example *
;* Made as help to demo and game creaters *
;* *
;* ASM-One example coded by Rune Gram-Madsen *
;* *
;* All rights reserved. Copyright (c) 1990 *
;************************************************
; Move the mouse around to draw a lot of lines.
;*****************
;* Constants *
;*****************
OldOpenLibrary = -408
CloseLibrary = -414
DMASET= %1000000111000000
; -----a-bcdefghij
; a: Blitter Nasty
; b: Bitplane DMA (if this isn't set, sprites disappear!)
; c: Copper DMA
; d: Blitter DMA
; e: Sprite DMA
; f: Disk DMA
; g-j: Audio 3-0 DMA
START:
MOVEM.L D0-D7/A0-A6,-(A7) ; Put registers on stack
;***********************************
;* CLOSE ALL SYSTEM INTERRUPTS *
;* *
;* START DEMO INTERRUPTS *
;***********************************
MOVE.L $4.W,A6 ; Exec pointer to A6
LEA.L GfxName(PC),A1 ; Set library pointer
MOVEQ #0,D0
JSR OldOpenLibrary(A6) ; Open graphics.library
MOVE.L D0,A1 ; Use Base-pointer
MOVE.L $26(A1),OLDCOP1 ; Store copper1 start addr
MOVE.L $32(A1),OLDCOP2 ; Store copper1 start addr
JSR CloseLibrary(A6) ; Close graphics library
LEA $DFF000,A6
MOVE.W $1C(A6),INTENA ; Store old INTENA
MOVE.W $2(A6),DMACON ; Store old DMACON
MOVE.W $10(A6),ADKCON ; Store old ADKCON
MOVE.W #$7FFF,$9A(A6) ; Clear interrupt enable
BSR.L Wait_Vert_Blank
MOVE.W #$7FFF,$96(A6) ; Clear DMA channels
MOVE.L #COPLIST,$80(A6) ; Copper1 start address
MOVE.W #DMASET!$8200,$96(A6) ; DMA kontrol data
MOVE.L $6C.W,OldInter ; Store old inter pointer
MOVE.L #INTER,$6C.W ; Set interrupt pointer
MOVE.W #$7FFF,$9C(A6) ; Clear request
MOVE.W #$C020,$9A(A6) ; Interrupt enable
;**** Your main routine ****
;**** Main Loop Test mouse button ****
LOOP:
BTST #6,$BFE001 ; Test left mouse button
BNE.S LOOP
;*****************************************
;* *
;* RESTORE SYSTEM INTERRUPTS ECT ECT *
;* *
;*****************************************
LEA $DFF000,A6
MOVE.W #$7FFF,$9A(A6) ; Disable interrupts
BSR.S Wait_Vert_Blank
MOVE.W #$7FFF,$96(A6)
MOVE.L OldCop1(PC),$80(A6) ; Restore old copper1
MOVE.L OldCop2(PC),$84(A6) ; Restore old copper1
MOVE.L OldInter(PC),$6C.W ; Restore inter pointer
MOVE.W DMACON,D0 ; Restore old DMACON
OR.W #$8000,D0
MOVE.W D0,$96(A6)
MOVE.W ADKCON,D0 ; Restore old ADKCON
OR.W #$8000,D0
MOVE.W D0,$9E(A6)
MOVE.W INTENA,D0 ; Restore inter data
OR.W #$C000,D0
MOVE.W #$7FFF,$9C(A6)
MOVE.W D0,$9A(A6)
MOVEM.L (A7)+,D0-D7/A0-A6 ; Get registers from stack
RTS
;*** WAIT VERTICAL BLANK ***
Wait_Vert_Blank:
BTST #0,$5(A6)
BEQ.S Wait_Vert_Blank
.loop BTST #0,$5(A6)
BNE.S .loop
RTS
;*** DATA AREA ***
GfxName DC.B 'graphics.library',0
even
DosBase DC.L 0
OldInter DC.L 0
OldCop1 DC.L 0
OldCop2 DC.L 0
INTENA DC.W 0
DMACON DC.W 0
ADKCON DC.W 0
;**********************************
;* *
;* INTERRUPT ROUTINE. LEVEL 3 *
;* *
;**********************************
INTER:
MOVEM.L D0-D7/A0-A6,-(A7) ; Put registers on stack
LEA.L $DFF000,A6
MOVE.L #SCREEN,$E0(A6)
;--- Place your interrupt routine here ---
BSR.S INITLINE ; Init line registers
MOVEQ #0,D0 ; Start X - Y coords
MOVEQ #0,D1
MOVEQ #0,D3 ; End X - Y coords
MOVEQ #0,D2
MOVE.W $A(a6),D3 ; Get mouse position
MOVE.B D3,D2
LSR.W #8,D3
BSR.S DRAWLINE ; Draw the line
MOVE.W #$4020,$9C(A6) ; Clear interrupt request
MOVEM.L (A7)+,D0-D7/A0-A6 ; Get registers from stack
RTE
;********************
;* Init line draw *
;********************
SINGLE = 0 ; 2 = SINGLE BIT WIDTH
BYTEWIDTH = 40
; The below registers only have to be set once each time
; you want to draw one or more lines.
INITLINE:
LEA.L $DFF000,A6
.WAIT: BTST #$6,$2(A6)
BNE.S .WAIT
MOVEQ #-1,D1
MOVE.L D1,$44(A6) ; FirstLastMask
MOVE.W #$8000,$74(A6) ; BLT data A
MOVE.W #BYTEWIDTH,$60(A6) ; Tot.Screen Width
MOVE.W #$FFFF,$72(A6)
LEA.L SCREEN,A5
RTS
;*****************
;* DRAW LINE *
;*****************
; USES D0/D1/D2/D3/D4/D7/A5/A6
DRAWLINE:
SUB.W D3,D1
MULU #40,D3 ; ScreenWidth * D3
MOVEQ #$F,D4
AND.W D2,D4 ; Get lowest bits from D2
;--------- SELECT OCTANT ---------
SUB.W D2,D0
BLT.S DRAW_DONT0146
TST.W D1
BLT.S DRAW_DONT04
CMP.W D0,D1
BGE.S DRAW_SELECT0
MOVEQ #$11+SINGLE,D7 ; Select Oct 4
BRA.S DRAW_OCTSELECTED
DRAW_SELECT0:
MOVEQ #1+SINGLE,D7 ; Select Oct 0
EXG D0,D1
BRA.S DRAW_OCTSELECTED
DRAW_DONT04:
NEG.W D1
CMP.W D0,D1
BGE.S DRAW_SELECT1
MOVEQ #$19+SINGLE,D7 ; Select Oct 6
BRA.S DRAW_OCTSELECTED
DRAW_SELECT1:
MOVEQ #5+SINGLE,D7 ; Select Oct 1
EXG D0,D1
BRA.S DRAW_OCTSELECTED
DRAW_DONT0146:
NEG.W D0
TST.W D1
BLT.S DRAW_DONT25
CMP.W D0,D1
BGE.S DRAW_SELECT2
MOVEQ #$15+SINGLE,D7 ; Select Oct 5
BRA.S DRAW_OCTSELECTED
DRAW_SELECT2:
MOVEQ #9+SINGLE,D7 ; Select Oct 2
EXG D0,D1
BRA.S DRAW_OCTSELECTED
DRAW_DONT25:
NEG.W D1
CMP.W D0,D1
BGE.S DRAW_SELECT3
MOVEQ #$1D+SINGLE,D7 ; Select Oct 7
BRA.S DRAW_OCTSELECTED
DRAW_SELECT3:
MOVEQ #$D+SINGLE,D7 ; Select Oct 3
EXG D0,D1
;--------- CALCULATE START ---------
DRAW_OCTSELECTED:
ADD.W D1,D1 ; 2*dy
ASR.W #3,D2 ; x=x/8
EXT.L D2
ADD.L D2,D3 ; d3 = x+y*40 = screen pos
MOVE.W D1,D2 ; d2 = 2*dy
SUB.W D0,D2 ; d2 = 2*dy-dx
BGE.S DRAW_DONTSETSIGN
ORI.W #$40,D7 ; dx < 2*dy
DRAW_DONTSETSIGN:
;--------- SET BLITTER ---------
.WAIT:
BTST #$6,$2(A6) ; Wait on the blitter
BNE.S .WAIT
MOVE.W D2,$52(A6) ; 2*dy-dx
MOVE.W D1,$62(A6) ; 2*d2
SUB.W D0,D2 ; d2 = 2*dy-dx-dx
MOVE.W D2,$64(A6) ; 2*dy-2*dx
;--------- MAKE LENGTH ---------
ASL.W #6,D0 ; d0 = 64*dx
ADD.W #$0042,D0 ; d0 = 64*(dx+1)+2
;--------- MAKE CONTROL 0+1 ---------
ROR.W #4,D4
ORI.W #$BEA,D4 ; $B4A - DMA + Minterm
SWAP D7
MOVE.W D4,D7
SWAP D7
ADD.L A5,D3 ; SCREEN PTR
MOVE.L D7,$40(A6) ; BLTCON0 + BLTCON1
MOVE.L D3,$48(A6) ; Source C
MOVE.L D3,$54(A6) ; Destination D
MOVE.W D0,$58(A6) ; Size
RTS
;*****************************
;* *
;* COPPER1 PROGRAM *
;* *
;*****************************
SECTION Copper,DATA_C
COPLIST:
DC.W $0100,$1200 ; Bit-Plane control reg.
DC.W $0102,$0000 ; Hor-Scroll
DC.W $0104,$0010 ; Sprite/Gfx priority
DC.W $0108,$0000 ; Modolu (odd)
DC.W $010A,$0000 ; Modolu (even)
DC.W $008E,$2C81 ; Screen Size
DC.W $0090,$2CC1 ; Screen Size
DC.W $0092,$0038 ; H-start
DC.W $0094,$00D0 ; H-stop
DC.W $0180,$0000 ; Color #0 = 000
DC.W $0182,$0FFF ; Color #1 = fff
DC.L $FFFFFFFE
;*****************************
;* *
;* SCREEN DATA AREA *
;* *
;*****************************
SECTION Screen,BSS_C
SCREEN DS.B 40*256
-
i have a startup source with a draw line code, it works on my A600, but on my A1200 i got corrupted screen graphics,
It's a bad startup code, not aware of the AGA.
See my home page for a better one (http://www.iki.fi/sintonen/src/hwstartup/hwstartup.asm).
The code also doesn't allocate the blitter (OwnBlitter + WaitBlit) for your own use, so it might mess up system blitter queue. The copperlist is not terminated with two $fffffffe's (two are required due to some copper bugs in some chipset revisions). OldOpenLibrary is obsolete and should not be used. The code actually stores old INTENA, DMACON and ADKCON without disabling interrupts. This leaves the code open for race conditions (wrong values might be restored at exit). The code is not aware of VBR (Vector Base Register, 68010-68060) that can be used to move the vector register array elsewhere in memory. Just poking/peeking $6C.w is not enough, it must be relative to VBR (for 68000 use base of 0).
.WAIT: BTST #6,$2(A6)
BNE.S .WAIT
is not enough to wait blitter. The BTST #6 must be done once before entering a loop, or the code might get false positive for blitter done (again some chipset revisions are buggy). Correct code:
BTST #6,$2(A6)
.WAIT: BTST #6,$2(A6)
BNE.S .WAIT
a lot of examples don't work because DevPac don't recognise instruction BLK, is a specific assembler instruction?
No.
it can be switched with other instruction compatible with DevPac?
dcb.size count,val
for example:
dcb.l 16,$715517
And the last question is about Blitter, to check if the blitter finished the operation, i test bit 6 on $DFF000 address
It's actually $DFF002 (dmaconr).
, but i found that some codes test bit 14, and DevPac says that you can test bits 0-7. Why some codes use bit 14?
Because btst is always byte operation and the bit number is masked by 7, and 14 & 7 = 6. Since the bits are counted from the LSB (rightmost bit) to MSB (leftmost bit), it doesn't really matter if you use 14 or 6, both fall to same bit. If you're testing bits 0 to 7, then you need to use btst #x,addr+1.
Some assemblers are a bit more lax about the constant value, but really you should use x-8 for the x = 8...15. Strictly speaking using btst #14,... is a bug, it should be btst #14-8,... or btst #14&7,...
So in short, the correct syntax that works for ALL assemblers (testing bit from 16bit memory location):
btst #x,addr+1 ; if x is 0..7
btst #x&7,addr ; if x is 8..15
And expanded to 32bit memory locations:
btst #x,addr+3 ; if x is 0..7
btst #x&7,addr+2 ; if x is 8..15
btst #x&7,addr+1 ; if x is 16..23
btst #x&7,addr ; if x is 24..31
-
Thanks a lot Piru!! very good explanation, i will take a look to your startup code.